]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
particles: fix bugs in cl_particles_quake
authorbones_was_here <bones_was_here@xonotic.au>
Tue, 7 May 2024 16:30:09 +0000 (02:30 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Thu, 9 May 2024 03:07:39 +0000 (13:07 +1000)
There was a segfault when CL_NewQuakeParticle->CL_NewParticle returned
NULL, and a missing break; in case pt_snow: in R_RenderParticles causing
fall-through to pt_explode.
Introduced in 58dc7879146968c2c07e1ffd2c521487a5e768d9, I missed them in
code review, oops.

Could have just added checks for NULL in CL_ParticleExplosion but these
kinds of exceptions can get messy if several accumulate so it seemed
better to merge them into the API which also made NULL checks redundant.

Changes the particle_t comments to doxygen comments.
Fixes indenting.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
cl_particles.c
cl_particles.h

index bb8840da27ca60a7855f6cd49d157b4617a41ba1..6a19bfd627b6e4f5d576854a901597da493ff4d0 100644 (file)
@@ -793,7 +793,6 @@ particle_t *CL_NewParticle(
        part->vel[0] = pvx + velocityjitter * v[0];
        part->vel[1] = pvy + velocityjitter * v[1];
        part->vel[2] = pvz + velocityjitter * v[2];
-       part->time2 = 0;
        part->airfriction = pairfriction;
        part->liquidfriction = pliquidfriction;
        part->die = cl.time + lifetime;
@@ -831,6 +830,9 @@ particle_t *CL_NewParticle(
                        }
                }
        }
+       else if (part->typeindex == pt_explode || part->typeindex == pt_explode2)
+               part->time2 = rand()&3; // time2 is used to progress the colour ramp index
+
 #if 0
        else if (part->bounce != 0 && part->gravity == 0 && part->typeindex != pt_snow)
        {
@@ -866,6 +868,7 @@ particle_t *CL_NewParticle(
  */
 particle_t *CL_NewQuakeParticle(
        const vec3_t origin,
+       const unsigned short ptypeindex,
        const int color_1,
        const int color_2,
        const float gravity,
@@ -891,7 +894,7 @@ particle_t *CL_NewQuakeParticle(
 
        return CL_NewParticle(
                origin,
-               pt_alphastatic,      // type
+               ptypeindex,          // type
                color_1,
                color_2,
                texture,
@@ -1043,6 +1046,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        int k = particlepalette[(palettecolor & ~7) + (rand()&7)];
                                        CL_NewQuakeParticle(
                                                center,                                      // origin
+                                               pt_alphastatic,                              // type
                                                k,                                           // color 1
                                                k,                                           // color 2
                                                0.15,                                        // gravity
@@ -1421,7 +1425,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        if (cl_particles_quake.integer)
                                        {
                                                color = particlepalette[67 + (rand()&3)];
-                                               CL_NewQuakeParticle(center, color, color, 0.25, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 2);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0.25, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 2);
                                        }
                                        else
                                        {
@@ -1435,7 +1439,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        {
                                                dec = 6;
                                                color = particlepalette[67 + (rand()&3)];
-                                               CL_NewQuakeParticle(center, color, color, 0.25, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 2);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0.25, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 2);
                                        }
                                        else
                                        {
@@ -1452,7 +1456,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        {
                                                r = rand()&3;
                                                color = particlepalette[ramp3[r]];
-                                               CL_NewQuakeParticle(center, color, color, -0.10, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 0.1372549 * (6 - r));
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, -0.10, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 0.1372549 * (6 - r));
                                        }
                                        else
                                        {
@@ -1466,7 +1470,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        {
                                                r = 2 + (rand()%4);
                                                color = particlepalette[ramp3[r]];
-                                               CL_NewQuakeParticle(center, color, color, -0.15, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 0.1372549 * (6 - r));
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, -0.15, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 3, 0, 0.1372549 * (6 - r));
                                        }
                                        else
                                        {
@@ -1479,8 +1483,8 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        {
                                                dec = 6;
                                                color = particlepalette[52 + (rand()&7)];
-                                               CL_NewQuakeParticle(center, color, color, 0, pos[0], pos[1], pos[2], 30*dir[1], 30*-dir[0], 0, 0, 0, 0, 0, 0.5);
-                                               CL_NewQuakeParticle(center, color, color, 0, pos[0], pos[1], pos[2], 30*-dir[1], 30*dir[0], 0, 0, 0, 0, 0, 0.5);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0, pos[0], pos[1], pos[2], 30*dir[1], 30*-dir[0], 0, 0, 0, 0, 0, 0.5);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0, pos[0], pos[1], pos[2], 30*-dir[1], 30*dir[0], 0, 0, 0, 0, 0, 0.5);
                                        }
                                        else if (gamemode == GAME_GOODVSBAD2)
                                        {
@@ -1499,8 +1503,8 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        {
                                                dec = 6;
                                                color = particlepalette[230 + (rand()&7)];
-                                               CL_NewQuakeParticle(center, color, color, 0, pos[0], pos[1], pos[2], 30 *  dir[1], 30 * -dir[0], 0, 0, 0, 0, 0, 0.5);
-                                               CL_NewQuakeParticle(center, color, color, 0, pos[0], pos[1], pos[2], 30 * -dir[1], 30 *  dir[0], 0, 0, 0, 0, 0, 0.5);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0, pos[0], pos[1], pos[2], 30 *  dir[1], 30 * -dir[0], 0, 0, 0, 0, 0, 0.5);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0, pos[0], pos[1], pos[2], 30 * -dir[1], 30 *  dir[0], 0, 0, 0, 0, 0, 0.5);
                                        }
                                        else
                                        {
@@ -1513,7 +1517,7 @@ static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const v
                                        if (cl_particles_quake.integer)
                                        {
                                                color = particlepalette[152 + (rand()&3)];
-                                               CL_NewQuakeParticle(center, color, color, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 8, 0, 0.3);
+                                               CL_NewQuakeParticle(center, pt_alphastatic, color, color, 0, pos[0], pos[1], pos[2], 0, 0, 0, 0, 0, 8, 0, 0.3);
                                        }
                                        else if (gamemode == GAME_GOODVSBAD2)
                                        {
@@ -1936,7 +1940,6 @@ void CL_ParticleExplosion (const vec3_t org)
 {
        int i;
        trace_t trace;
-       particle_t *particle;
 
        R_Stain(org, 96, 40, 40, 40, 64, 88, 88, 88, 64);
        CL_SpawnDecalParticleForPoint(org, 40, 48, 255, tex_bulletdecal[rand()&7], 0xFFFFFF, 0xFFFFFF);
@@ -1952,8 +1955,9 @@ void CL_ParticleExplosion (const vec3_t org)
                        {
                                color = particlepalette[ramp1[r]];
 
-                               particle = CL_NewQuakeParticle(
+                               CL_NewQuakeParticle(
                                        org,
+                                       pt_explode,
                                        color, color,
                                        0.05,                        // gravity
                                        org[0], org[1], org[2],      // offset
@@ -1964,14 +1968,14 @@ void CL_ParticleExplosion (const vec3_t org)
                                        256,                         // velocity jitter
                                        5                            // lifetime
                                );
-                               particle->typeindex = pt_explode;
                        }
                        else
                        {
                                color = particlepalette[ramp2[r]];
 
-                               particle = CL_NewQuakeParticle(
+                               CL_NewQuakeParticle(
                                        org,
+                                       pt_explode2,
                                        color, color,
                                        0.05,                        // gravity
                                        org[0], org[1], org[2],      // offset
@@ -1982,11 +1986,7 @@ void CL_ParticleExplosion (const vec3_t org)
                                        256,                         // velocity jitter
                                        5                            // lifetime
                                );
-
-                               particle->typeindex = pt_explode2;
                        }
-
-                       particle->time2 = r;  // time2 is used to progress the colour ramp index
                }
        }
        else
@@ -2040,7 +2040,7 @@ void CL_ParticleExplosion2 (const vec3_t org, int colorStart, int colorLength)
        {
                k = particlepalette[colorStart + (i % colorLength)];
                if (cl_particles_quake.integer)
-                       CL_NewQuakeParticle(org, k, k, 0, org[0], org[1], org[2], 0, 0, 0, -4, -4, 16, 256, 0.3);
+                       CL_NewQuakeParticle(org, pt_alphastatic, k, k, 0, org[0], org[1], org[2], 0, 0, 0, -4, -4, 16, 256, 0.3);
                else
                        CL_NewParticle(org, pt_alphastatic, k, k, tex_particle, lhrandom(0.5, 1.5), 0, 255, 512, 0, 0, org[0], org[1], org[2], 0, 0, 0, lhrandom(1.5, 3), lhrandom(1.5, 3), 8, 192, true, 0, 1, PBLEND_ALPHA, PARTICLE_BILLBOARD, -1, -1, -1, 1, 1, 0, 0, NULL);
        }
@@ -2921,14 +2921,14 @@ void R_DrawParticles (void)
        frametime = bound(0, cl.time - cl.particles_updatetime, 1);
        cl.particles_updatetime = bound(cl.time - 1, cl.particles_updatetime + frametime, cl.time + 1);
 
-       // Handling of the colour ramp for pt_explode and pt_explode2
-       pt_explode_frame_interval = frametime * 10;
-       pt_explode2_frame_interval = frametime * 15;
-
        // LadyHavoc: early out conditions
        if (!cl.num_particles)
                return;
 
+       // Handling of the colour ramp for pt_explode and pt_explode2
+       pt_explode_frame_interval = frametime * 10;
+       pt_explode2_frame_interval = frametime * 15;
+
        minparticledist_start = DotProduct(r_refdef.view.origin, r_refdef.view.forward) + r_drawparticles_nearclip_min.value;
        gravity = frametime * cl.movevars_gravity;
        update = frametime > 0;
@@ -3099,35 +3099,33 @@ void R_DrawParticles (void)
                                        a = CL_PointSuperContents(p->org);
                                        if (a & (SUPERCONTENTS_SOLID | SUPERCONTENTS_LIQUIDSMASK))
                                                goto killparticle;
-                                       case pt_explode:
-                                               // Progress the particle colour up the ramp
-                                               p->time2 += pt_explode_frame_interval;
-                                               if (p->time2 >= 8)
-                                               {
-                                                       p->die = -1;
-                                               }
-                                               else {
-                                                       color = particlepalette[ramp1[(int)p->time2]];
-                                                       p->color[0] = color >> 16;
-                                                       p->color[1] = color >>  8;
-                                                       p->color[2] = color >>  0;
-                                               }
-                                               break;
-
-                                       case pt_explode2:
-                                               // Progress the particle colour up the ramp
-                                               p->time2 += pt_explode2_frame_interval;
-                                               if (p->time2 >= 8)
-                                               {
-                                                       p->die = -1;
-                                               }
-                                               else {
-                                                       color = particlepalette[ramp2[(int)p->time2]];
-                                                       p->color[0] = color >> 16;
-                                                       p->color[1] = color >>  8;
-                                                       p->color[2] = color >>  0;
-                                               }
-                                               break;
+                                       break;
+                               case pt_explode:
+                                       // Progress the particle colour up the ramp
+                                       p->time2 += pt_explode_frame_interval;
+                                       if (p->time2 >= 8)
+                                               p->die = -1;
+                                       else
+                                       {
+                                               color = particlepalette[ramp1[(int)p->time2]];
+                                               p->color[0] = color >> 16;
+                                               p->color[1] = color >>  8;
+                                               p->color[2] = color >>  0;
+                                       }
+                                       break;
+                               case pt_explode2:
+                                       // Progress the particle colour up the ramp
+                                       p->time2 += pt_explode2_frame_interval;
+                                       if (p->time2 >= 8)
+                                               p->die = -1;
+                                       else
+                                       {
+                                               color = particlepalette[ramp2[(int)p->time2]];
+                                               p->color[0] = color >> 16;
+                                               p->color[1] = color >>  8;
+                                               p->color[2] = color >>  0;
+                                       }
+                                       break;
                                default:
                                        break;
                                }
index ed8bb320fdd04891b19bdf9fb7886ee4d0c90b83..38f36ad87295bf0dac304ff93039ef43c71ec0d7 100644 (file)
@@ -82,34 +82,34 @@ typedef struct particle_s
        // for faster batch rendering, particles are rendered in groups by effect (resulting in less perfect sorting but far less state changes)
 
        // fields used by rendering: (48 bytes)
-       vec3_t          sortorigin; // sort by this group origin, not particle org
+       vec3_t          sortorigin; ///< sort by this group origin, not particle org
        vec3_t          org;
-       vec3_t          vel; // velocity of particle, or orientation of decal, or end point of beam
+       vec3_t          vel;        ///< velocity of particle, or orientation of decal, or end point of beam
        float           size;
-       float           alpha; // 0-255
-       float           stretch; // only for sparks
+       float           alpha;      ///< 0-255
+       float           stretch;    ///< only for sparks
 
        // fields not used by rendering:  (44 bytes)
        float           stainsize;
        float           stainalpha;
-       float           sizeincrease; // rate of size change per second
-       float           alphafade; // how much alpha reduces per second
-       float           time2; // used for snow fluttering and decal fade
-       float           bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
-       float           gravity; // how much gravity affects this particle (1.0 = normal gravity, 0.0 = none)
-       float           airfriction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
-       float           liquidfriction; // how much liquid friction affects this object (objects with a low mass/size ratio tend to get more liquid friction)
-//     float           delayedcollisions; // time that p->bounce becomes active
-       float           delayedspawn; // time that particle appears and begins moving
-       float           die; // time when this particle should be removed, regardless of alpha
+       float           sizeincrease;   ///< rate of size change per second
+       float           alphafade;      ///< how much alpha reduces per second
+       float           time2;          ///< used for snow fluttering, decal fade, explosion colour ramp
+       float           bounce;         ///< how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
+       float           gravity;        ///< how much gravity affects this particle (1.0 = normal gravity, 0.0 = none)
+       float           airfriction;    ///< how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
+       float           liquidfriction; ///< how much liquid friction affects this object (objects with a low mass/size ratio tend to get more liquid friction)
+//     float           delayedcollisions; ///< time that p->bounce becomes active
+       float           delayedspawn;   ///< time that particle appears and begins moving
+       float           die;            ///< time when this particle should be removed, regardless of alpha
 
        // short variables grouped to save memory (4 bytes)
-       short                   angle; // base rotation of particle
-       short                   spin; // geometry rotation speed around the particle center normal
+       short           angle; ///< base rotation of particle
+       short           spin;  ///< geometry rotation speed around the particle center normal
 
        // byte variables grouped to save memory (12 bytes)
        unsigned char   color[3];
-       unsigned char   qualityreduction; // enables skipping of this particle according to r_refdef.view.qualityreduction
+       unsigned char   qualityreduction; ///< enables skipping of this particle according to r_refdef.view.qualityreduction
        unsigned char   typeindex;
        unsigned char   blendmode;
        unsigned char   orientation;
@@ -123,7 +123,7 @@ void CL_Particles_Clear(void);
 void CL_Particles_Init(void);
 void CL_Particles_Shutdown(void);
 particle_t *CL_NewParticle(const vec3_t sortorigin, unsigned short ptypeindex, int pcolor1, int pcolor2, int ptex, float psize, float psizeincrease, float palpha, float palphafade, float pgravity, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz, float pairfriction, float pliquidfriction, float originjitter, float velocityjitter, qbool pqualityreduction, float lifetime, float stretch, pblend_t blendmode, porientation_t orientation, int staincolor1, int staincolor2, int staintex, float stainalpha, float stainsize, float angle, float spin, float tint[4]);
-particle_t *CL_NewQuakeParticle(const vec3_t origin, const int color_1, const int color_2, const float gravity, const float offset_x, const float offset_y, const float offset_z, const float velocity_offset_x, const float velocity_offset_y, const float velocity_offset_z, const float air_friction, const float liquid_friction, const float origin_jitter, const float velocity_jitter, const float lifetime);
+particle_t *CL_NewQuakeParticle(const vec3_t origin, const unsigned short ptypeindex, const int color_1, const int color_2, const float gravity, const float offset_x, const float offset_y, const float offset_z, const float velocity_offset_x, const float velocity_offset_y, const float velocity_offset_z, const float air_friction, const float liquid_friction, const float origin_jitter, const float velocity_jitter, const float lifetime);
 
 typedef enum effectnameindex_s
 {
@@ -179,4 +179,4 @@ void CL_EntityParticles (const struct entity_s *ent);
 void CL_ParticleExplosion (const vec3_t org);
 void CL_ParticleExplosion2 (const vec3_t org, int colorStart, int colorLength);
 
-#endif
\ No newline at end of file
+#endif