]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_tent.c
rewrote memory system entirely (hunk, cache, and zone are gone, memory pools replaced...
[xonotic/darkplaces.git] / cl_tent.c
index c633df63c81bd275af90a699e540e6b68d3e2d0d..d38ee2705302e708f7902778d315d78642c44c3b 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -21,17 +21,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
+cvar_t cl_glowinglightning = {CVAR_SAVE, "cl_glowinglightning", "1"};
+
 int                    num_temp_entities;
 entity_t       cl_temp_entities[MAX_TEMP_ENTITIES];
 beam_t         cl_beams[MAX_BEAMS];
 
-sfx_t                  *cl_sfx_wizhit;
-sfx_t                  *cl_sfx_knighthit;
-sfx_t                  *cl_sfx_tink1;
-sfx_t                  *cl_sfx_ric1;
-sfx_t                  *cl_sfx_ric2;
-sfx_t                  *cl_sfx_ric3;
-sfx_t                  *cl_sfx_r_exp3;
+model_t                *cl_model_bolt = NULL;
+model_t                *cl_model_bolt2 = NULL;
+model_t                *cl_model_bolt3 = NULL;
+model_t                *cl_model_beam = NULL;
+
+sfx_t          *cl_sfx_wizhit;
+sfx_t          *cl_sfx_knighthit;
+sfx_t          *cl_sfx_tink1;
+sfx_t          *cl_sfx_ric1;
+sfx_t          *cl_sfx_ric2;
+sfx_t          *cl_sfx_ric3;
+sfx_t          *cl_sfx_r_exp3;
 
 /*
 =================
@@ -40,6 +47,7 @@ CL_ParseTEnt
 */
 void CL_InitTEnts (void)
 {
+       Cvar_RegisterVariable(&cl_glowinglightning);
        cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
        cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
        cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
@@ -60,16 +68,10 @@ void CL_ParseBeam (model_t *m)
        vec3_t  start, end;
        beam_t  *b;
        int             i;
-       
+
        ent = MSG_ReadShort ();
-       
-       start[0] = MSG_ReadCoord ();
-       start[1] = MSG_ReadCoord ();
-       start[2] = MSG_ReadCoord ();
-       
-       end[0] = MSG_ReadCoord ();
-       end[1] = MSG_ReadCoord ();
-       end[2] = MSG_ReadCoord ();
+       MSG_ReadVector(start);
+       MSG_ReadVector(end);
 
 // override any beam with the same entity
        for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
@@ -99,10 +101,6 @@ void CL_ParseBeam (model_t *m)
        Con_Printf ("beam list overflow!\n");   
 }
 
-void R_BlastParticles(vec3_t org, vec_t radius, vec_t power);
-void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count);
-void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel);
-void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type);
 
 /*
 =================
@@ -115,38 +113,32 @@ void CL_ParseTEnt (void)
        vec3_t  pos;
        vec3_t  dir;
        vec3_t  pos2;
-       dlight_t        *dl;
+       vec3_t  color;
        int             rnd;
        int             colorStart, colorLength, count;
-       float   velspeed;
+       float   velspeed, radius;
        byte *tempcolor;
 
        type = MSG_ReadByte ();
        switch (type)
        {
        case TE_WIZSPIKE:                       // spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_RunParticleEffect (pos, vec3_origin, 20, 30);
+               MSG_ReadVector(pos);
+               CL_RunParticleEffect (pos, vec3_origin, 20, 30);
                S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
                break;
                
        case TE_KNIGHTSPIKE:                    // spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_RunParticleEffect (pos, vec3_origin, 226, 20);
+               MSG_ReadVector(pos);
+               CL_RunParticleEffect (pos, vec3_origin, 226, 20);
                S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
                break;
                
        case TE_SPIKE:                  // spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                // LordHavoc: changed to spark shower
-               R_SparkShower(pos, vec3_origin, 15, 0);
-               //R_RunParticleEffect (pos, vec3_origin, 0, 10);
+               CL_SparkShower(pos, vec3_origin, 15);
+               //CL_RunParticleEffect (pos, vec3_origin, 0, 10);
                if ( rand() % 5 )
                        S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
                else
@@ -161,18 +153,11 @@ void CL_ParseTEnt (void)
                }
                break;
        case TE_SPIKEQUAD:                      // quad spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                // LordHavoc: changed to spark shower
-               R_SparkShower(pos, vec3_origin, 15, 0);
-               //R_RunParticleEffect (pos, vec3_origin, 0, 10);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 200;
-               dl->die = cl.time + 0.2;
-               dl->decay = 1000;
-               dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
+               CL_SparkShower(pos, vec3_origin, 15);
+               //CL_RunParticleEffect (pos, vec3_origin, 0, 10);
+               CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                if ( rand() % 5 )
                        S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
@@ -188,12 +173,10 @@ void CL_ParseTEnt (void)
                }
                break;
        case TE_SUPERSPIKE:                     // super spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                // LordHavoc: changed to dust shower
-               R_SparkShower(pos, vec3_origin, 30, 0);
-               //R_RunParticleEffect (pos, vec3_origin, 0, 20);
+               CL_SparkShower(pos, vec3_origin, 30);
+               //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
                if ( rand() % 5 )
                        S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
                else
@@ -208,18 +191,11 @@ void CL_ParseTEnt (void)
                }
                break;
        case TE_SUPERSPIKEQUAD:                 // quad super spike hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                // LordHavoc: changed to dust shower
-               R_SparkShower(pos, vec3_origin, 30, 0);
-               //R_RunParticleEffect (pos, vec3_origin, 0, 20);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 200;
-               dl->die = cl.time + 0.2;
-               dl->decay = 1000;
-               dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
+               CL_SparkShower(pos, vec3_origin, 30);
+               //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
+               CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                if ( rand() % 5 )
                        S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
                else
@@ -235,251 +211,213 @@ void CL_ParseTEnt (void)
                break;
                // LordHavoc: added for improved blood splatters
        case TE_BLOOD:  // blood puff
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte (); // amount of particles
-               R_SparkShower(pos, dir, count, 1);
+               CL_BloodPuff(pos, dir, count);
+               break;
+       case TE_BLOOD2: // blood puff
+               MSG_ReadVector(pos);
+               CL_BloodPuff(pos, vec3_origin, 10);
                break;
        case TE_SPARK:  // spark shower
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte (); // amount of particles
-               R_SparkShower(pos, dir, count, 0);
+               CL_SparkShower(pos, dir, count);
                break;
                // LordHavoc: added for improved gore
        case TE_BLOODSHOWER:    // vaporized body
-               pos[0] = MSG_ReadCoord (); // mins
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               dir[0] = MSG_ReadCoord (); // maxs
-               dir[1] = MSG_ReadCoord ();
-               dir[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos); // mins
+               MSG_ReadVector(pos2); // maxs
                velspeed = MSG_ReadCoord (); // speed
                count = MSG_ReadShort (); // number of particles
-               R_BloodShower(pos, dir, velspeed, count);
+               CL_BloodShower(pos, pos2, velspeed, count);
                break;
        case TE_PARTICLECUBE:   // general purpose particle effect
-               pos[0] = MSG_ReadCoord (); // mins
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               pos2[0] = MSG_ReadCoord (); // maxs
-               pos2[1] = MSG_ReadCoord ();
-               pos2[2] = MSG_ReadCoord ();
-               dir[0] = MSG_ReadCoord (); // dir
-               dir[1] = MSG_ReadCoord ();
-               dir[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos); // mins
+               MSG_ReadVector(pos2); // maxs
+               MSG_ReadVector(dir); // dir
                count = MSG_ReadShort (); // number of particles
                colorStart = MSG_ReadByte (); // color
                colorLength = MSG_ReadByte (); // gravity (1 or 0)
                velspeed = MSG_ReadCoord (); // randomvel
-               R_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
+               CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
                break;
 
        case TE_PARTICLERAIN:   // general purpose particle effect
-               pos[0] = MSG_ReadCoord (); // mins
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               pos2[0] = MSG_ReadCoord (); // maxs
-               pos2[1] = MSG_ReadCoord ();
-               pos2[2] = MSG_ReadCoord ();
-               dir[0] = MSG_ReadCoord (); // dir
-               dir[1] = MSG_ReadCoord ();
-               dir[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos); // mins
+               MSG_ReadVector(pos2); // maxs
+               MSG_ReadVector(dir); // dir
                count = MSG_ReadShort (); // number of particles
                colorStart = MSG_ReadByte (); // color
-               R_ParticleRain(pos, pos2, dir, count, colorStart, 0);
+               CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
                break;
 
        case TE_PARTICLESNOW:   // general purpose particle effect
-               pos[0] = MSG_ReadCoord (); // mins
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               pos2[0] = MSG_ReadCoord (); // maxs
-               pos2[1] = MSG_ReadCoord ();
-               pos2[2] = MSG_ReadCoord ();
-               dir[0] = MSG_ReadCoord (); // dir
-               dir[1] = MSG_ReadCoord ();
-               dir[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos); // mins
+               MSG_ReadVector(pos2); // maxs
+               MSG_ReadVector(dir); // dir
                count = MSG_ReadShort (); // number of particles
                colorStart = MSG_ReadByte (); // color
-               R_ParticleRain(pos, pos2, dir, count, colorStart, 1);
+               CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
                break;
 
        case TE_GUNSHOT:                        // bullet hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
                // LordHavoc: changed to dust shower
-               R_SparkShower(pos, vec3_origin, 15, 0);
-               //R_RunParticleEffect (pos, vec3_origin, 0, 20);
+               CL_SparkShower(pos, vec3_origin, 15);
+               //CL_RunParticleEffect (pos, vec3_origin, 0, 20);
                break;
 
        case TE_GUNSHOTQUAD:                    // quad bullet hitting wall
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_SparkShower(pos, vec3_origin, 15, 0);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 200;
-               dl->die = cl.time + 0.2;
-               dl->decay = 1000;
-               dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
+               MSG_ReadVector(pos);
+               CL_SparkShower(pos, vec3_origin, 15);
+               CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                break;
 
        case TE_EXPLOSION:                      // rocket explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_ParticleExplosion (pos, false);
-               R_BlastParticles (pos, 120, 120);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 350;
-               dl->die = cl.time + 0.5;
-               dl->decay = 700;
-               dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_ParticleExplosion (pos, false);
+//             CL_BlastParticles (pos, 120, 120);
+               CL_AllocDlight (NULL, pos, 350, 1.0f, 0.8f, 0.4f, 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
        case TE_EXPLOSIONQUAD:                  // quad rocket explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_ParticleExplosion (pos, false);
-               R_BlastParticles (pos, 120, 480);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 600;
-               dl->die = cl.time + 0.5;
-               dl->decay = 1200;
-               dl->color[0] = 0.5;dl->color[1] = 0.4;dl->color[2] = 1.0;
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_ParticleExplosion (pos, false);
+//             CL_BlastParticles (pos, 120, 480);
+               CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
                /*
        case TE_SMOKEEXPLOSION:                 // rocket explosion with a cloud of smoke
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_ParticleExplosion (pos, true);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 350;
-               dl->die = cl.time + 0.5;
-               dl->decay = 300;
-               dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_ParticleExplosion (pos, true);
+               CL_AllocDlight (NULL, pos, 350, 1.0f, 0.8f, 0.4f, 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
                */
 
        case TE_EXPLOSION3:                             // Nehahra movie colored lighting explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_ParticleExplosion (pos, false);
-               R_BlastParticles (pos, 120, 120);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 350;
-               dl->die = cl.time + 0.5;
-               dl->decay = 700;
-               dl->color[0] = MSG_ReadCoord();dl->color[1] = MSG_ReadCoord();dl->color[2] = MSG_ReadCoord();
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_ParticleExplosion (pos, false);
+//             CL_BlastParticles (pos, 120, 120);
+               CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
        case TE_EXPLOSIONRGB:                   // colored lighting explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_ParticleExplosion (pos, false);
-               R_BlastParticles (pos, 120, 120);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 350;
-               dl->die = cl.time + 0.5;
-               dl->decay = 700;
-               dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0);
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_ParticleExplosion (pos, false);
+//             CL_BlastParticles (pos, 120, 120);
+               color[0] = MSG_ReadByte() * (1.0 / 255.0);
+               color[1] = MSG_ReadByte() * (1.0 / 255.0);
+               color[2] = MSG_ReadByte() * (1.0 / 255.0);
+               CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
        case TE_TAREXPLOSION:                   // tarbaby explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
-               R_BlobExplosion (pos);
-               R_BlastParticles (pos, 120, 120);
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_BlobExplosion (pos);
+//             CL_BlastParticles (pos, 120, 120);
 
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 600;
-               dl->die = cl.time + 0.5;
-               dl->decay = 1200;
-               dl->color[0] = 0.8;dl->color[1] = 0.4;dl->color[2] = 1.0;
+               CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
+       case TE_SMALLFLASH:
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
+               break;
+
+       case TE_CUSTOMFLASH:
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               radius = MSG_ReadByte() * 8;
+               velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
+               color[0] = MSG_ReadByte() * (1.0 / 255.0);
+               color[1] = MSG_ReadByte() * (1.0 / 255.0);
+               color[2] = MSG_ReadByte() * (1.0 / 255.0);
+               CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
+               break;
+
+       case TE_FLAMEJET:
+               MSG_ReadVector(pos);
+               MSG_ReadVector(dir);
+               count = MSG_ReadByte();
+               CL_Flames(pos, dir, count);
+               break;
+
        case TE_LIGHTNING1:                             // lightning bolts
-               CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
+               if (!cl_model_bolt)
+                       cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, true, false);
+               CL_ParseBeam (cl_model_bolt);
                break;
-       
+
        case TE_LIGHTNING2:                             // lightning bolts
-               CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
+               if (!cl_model_bolt2)
+                       cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, true, false);
+               CL_ParseBeam (cl_model_bolt2);
                break;
-       
+
        case TE_LIGHTNING3:                             // lightning bolts
-               CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
+               if (!cl_model_bolt3)
+                       cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, true, false);
+               CL_ParseBeam (cl_model_bolt3);
                break;
 
-// PGM 01/21/97 
+// PGM 01/21/97
        case TE_BEAM:                           // grappling hook beam
-               CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
+               if (!cl_model_beam)
+                       cl_model_beam = Mod_ForName("progs/beam.mdl", true, true, false);
+               CL_ParseBeam (cl_model_beam);
                break;
 // PGM 01/21/97
 
 // LordHavoc: for compatibility with the Nehahra movie...
        case TE_LIGHTNING4NEH:
-               CL_ParseBeam (Mod_ForName(MSG_ReadString(), true));
+               CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false));
                break;
 
        case TE_LAVASPLASH:     
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
-               R_LavaSplash (pos);
+               CL_LavaSplash (pos);
                break;
        
        case TE_TELEPORT:
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
-               R_TeleportSplash (pos);
+               CL_TeleportSplash (pos);
                break;
                
        case TE_EXPLOSION2:                             // color mapped explosion
-               pos[0] = MSG_ReadCoord ();
-               pos[1] = MSG_ReadCoord ();
-               pos[2] = MSG_ReadCoord ();
+               MSG_ReadVector(pos);
+               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                colorStart = MSG_ReadByte ();
                colorLength = MSG_ReadByte ();
-               R_ParticleExplosion2 (pos, colorStart, colorLength);
-               R_BlastParticles (pos, 80, 80);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 350;
-               dl->die = cl.time + 0.5;
-               dl->decay = 700;
+               CL_ParticleExplosion2 (pos, colorStart, colorLength);
+//             CL_BlastParticles (pos, 80, 80);
                tempcolor = (byte *)&d_8to24table[(rand()%colorLength) + colorStart];
-               dl->color[0] = tempcolor[0] * (1.0f / 255.0f);dl->color[1] = tempcolor[1] * (1.0f / 255.0f);dl->color[2] = tempcolor[2] * (1.0f / 255.0f);
+               CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
                
@@ -498,21 +436,17 @@ entity_t *CL_NewTempEntity (void)
 {
        entity_t        *ent;
 
-       if (cl_numvisedicts == MAX_VISEDICTS)
+       if (cl_numvisedicts >= MAX_VISEDICTS)
                return NULL;
-       if (num_temp_entities == MAX_TEMP_ENTITIES)
+       if (num_temp_entities >= MAX_TEMP_ENTITIES)
                return NULL;
-       ent = &cl_temp_entities[num_temp_entities];
+       ent = &cl_temp_entities[num_temp_entities++];
        memset (ent, 0, sizeof(*ent));
-       num_temp_entities++;
-       cl_visedicts[cl_numvisedicts] = ent;
-       cl_numvisedicts++;
-
-//     ent->colormap = vid.colormap;
-       ent->colormap = 0;
-       ent->scale = 1;
-       ent->alpha = 1;
-       ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
+       cl_visedicts[cl_numvisedicts++] = ent;
+
+       ent->render.colormap = -1; // no special coloring
+       ent->render.scale = 1;
+       ent->render.alpha = 1;
        return ent;
 }
 
@@ -531,7 +465,6 @@ void CL_UpdateTEnts (void)
        entity_t        *ent;
        float           yaw, pitch;
        float           forward;
-       dlight_t        *dl;
 
        num_temp_entities = 0;
 
@@ -541,13 +474,11 @@ void CL_UpdateTEnts (void)
                if (!b->model || b->endtime < cl.time)
                        continue;
 
-       // if coming from the player, update the start position
+               // if coming from the player, update the start position
                if (b->entity == cl.viewentity)
-               {
-                       VectorCopy (cl_entities[cl.viewentity].origin, b->start);
-               }
+                       VectorCopy (cl_entities[cl.viewentity].render.origin, b->start);
 
-       // calculate pitch and yaw
+               // calculate pitch and yaw
                VectorSubtract (b->end, b->start, dist);
 
                if (dist[1] == 0 && dist[0] == 0)
@@ -570,7 +501,7 @@ void CL_UpdateTEnts (void)
                                pitch += 360;
                }
 
-       // add new entities for the lightning
+               // add new entities for the lightning
                VectorCopy (b->start, org);
                d = VectorNormalizeLength(dist);
                while (d > 0)
@@ -578,24 +509,21 @@ void CL_UpdateTEnts (void)
                        ent = CL_NewTempEntity ();
                        if (!ent)
                                return;
-                       VectorCopy (org, ent->origin);
-                       ent->model = b->model;
-                       ent->effects = EF_FULLBRIGHT;
-                       ent->angles[0] = pitch;
-                       ent->angles[1] = yaw;
-                       ent->angles[2] = rand()%360;
-
-                       dl = CL_AllocDlight (0);
-                       VectorCopy (ent->origin,  dl->origin);
-                       dl->radius = 100 + (rand()&31);
-                       dl->die = cl.time + 0.001;
-                       dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 1;
+                       VectorCopy (org, ent->render.origin);
+                       ent->render.model = b->model;
+                       ent->render.effects = EF_FULLBRIGHT;
+                       ent->render.angles[0] = pitch;
+                       ent->render.angles[1] = yaw;
+                       ent->render.angles[2] = rand()%360;
+
+                       if (cl_glowinglightning.value > 0)
+                               CL_AllocDlight(&ent->render, ent->render.origin, lhrandom(200, 240), cl_glowinglightning.value * 0.25f, cl_glowinglightning.value * 0.25f, cl_glowinglightning.value * 0.25f, 0, 0);
 
                        VectorMA(org, 30, dist, org);
                        d -= 30;
                }
        }
-       
+
 }