]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
added newmap function to render modules (so explosions and other things are reset...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 20 Apr 2001 15:38:28 +0000 (15:38 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 20 Apr 2001 15:38:28 +0000 (15:38 +0000)
CL_AllocDlight redesigned (takes all settings for dlight on parameter line)
dlights now use a pointer to their owner entity instead of a key number
light emitting entities now glow properly (directional lighting disabled on the entity that owns the dlight)
cl_shownet no longer spews empty lines when recieving less updates from server than client framerate
some whitespace cleanup
fixed some missing parentheses on a condition in R_BuildLightmap (mixed &&, &, and ||, eek)
fixed vertex array problems with fog sky
increased MAX_TRANSPOLYS from 8192 to 65536
added a general purpose decal engine, superior to the decal particles (lower CPU use, better lighting)
added bullet hole decals and bullet hole texture generator
added r_speeds2 time reporting for moveexplosions, drawexplosions, and drawdecals
cleaned up dlight logic, all code now relies on radius, which is cleared when the dlight dies, this removed all potential flickering problems and offers a minor speedup
optimized R_ResampleTexture further to improve load times
moved heap size commandline parameter stuff from platform specific startup code to Host_Init, now all platforms understand -mem, -winmem, and -heapsize
WAD3 texture transparency now supported again
r_explosionclip cvar is now saved to config
r_drawexplosions cvar added
r_particles cvar is now saved to config
r_dynamicparticles cvar renamed to r_particles_lighting
r_particles_bloodshowers cvar added to disable blood shower effects
r_particles_blood cvar added to disable blood effects
r_particles_smoke cvar added to disable smoke effects
r_particles_sparks cvar added to disable spark effects
r_particles_bubbles cvar added to disable bubble effects
fixed smoke texture problem (0 alpha-noise portions were not written to texture, leaving portions of previous texture in buffer)
changed nearly every particle effect to look better and use less particles and fillrate, major speed gains resulted
blood particles no longer fade inflight as it made the effects less impressive and resulted in a lot of mostly transparent decals
major particle size bug fixed, all view aligned particles (everything but rain and decals) were 50% larger than they were supposed to be
particles now use transpolyvertub (unsigned byte colors) instead of transpolyvert for a speedup

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@189 d7cf8633-e32d-0410-b094-e92efae38249

34 files changed:
cl_effects.c
cl_main.c
cl_parse.c
cl_tent.c
client.h
fractalnoise.c
gl_draw.c
gl_models.c
gl_poly.c
gl_poly.h
gl_rmain.c
gl_rmisc.c
gl_screen.c
gl_textures.c
host.c
image.c
image.h
makefile
model_brush.c
quakedef.h
r_crosshairs.c
r_decals.c [new file with mode: 0644]
r_decals.h [new file with mode: 0644]
r_explosion.c
r_light.c
r_light.h
r_modules.c
r_modules.h
r_part.c
r_sprites.c
render.h
snd_win.c
sys_linux.c
sys_win.c

index 61630a22fcaae8d91a9f993b706752595c8ca61e..01bea5c92ec2d71ba4e4c14ed7fa506f37964d27 100644 (file)
@@ -51,11 +51,16 @@ void r_effects_shutdown()
 {
 }
 
+void r_effects_newmap()
+{
+       memset(effect, 0, sizeof(effect));
+}
+
 void CL_Effects_Init()
 {
        Cvar_RegisterVariable(&r_draweffects);
 
-       R_RegisterModule("R_Effects", r_effects_start, r_effects_shutdown);
+       R_RegisterModule("R_Effects", r_effects_start, r_effects_shutdown, r_effects_newmap);
 }
 
 void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate)
index 7a6623a102212c0725c05a2058d0ec3aa341b52d..40b42ebbec1fd21a6828cc516bfb8629c2fb88e2 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -286,42 +286,39 @@ CL_AllocDlight
 
 ===============
 */
-dlight_t *CL_AllocDlight (int key)
+void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime)
 {
        int             i;
        dlight_t        *dl;
 
 // first look for an exact key match
-       if (key)
+       if (ent)
        {
                dl = cl_dlights;
-               for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
-               {
-                       if (dl->key == key)
-                       {
-                               memset (dl, 0, sizeof(*dl));
-                               dl->key = key;
-                               return dl;
-                       }
-               }
+               for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+                       if (dl->ent == ent)
+                               goto dlightsetup;
        }
 
 // then look for anything else
        dl = cl_dlights;
-       for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
-       {
-               if (dl->die < cl.time)
-               {
-                       memset (dl, 0, sizeof(*dl));
-                       dl->key = key;
-                       return dl;
-               }
-       }
+       for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+               if (!dl->radius)
+                       goto dlightsetup;
 
-       dl = &cl_dlights[0];
+       // unable to find one
+       return;
+
+dlightsetup:
        memset (dl, 0, sizeof(*dl));
-       dl->key = key;
-       return dl;
+       dl->ent = ent;
+       VectorCopy(org, dl->origin);
+       dl->radius = radius;
+       dl->color[0] = red;
+       dl->color[1] = green;
+       dl->color[2] = blue;
+       dl->decay = decay;
+       dl->die = cl.time + lifetime;
 }
 
 
@@ -343,8 +340,13 @@ void CL_DecayLights (void)
        dl = cl_dlights;
        for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
        {
-               if (dl->die < cl.time || !dl->radius)
+               if (!dl->radius)
+                       continue;
+               if (dl->die < cl.time)
+               {
+                       dl->radius = 0;
                        continue;
+               }
 
                c_dlights++; // count every dlight in use
 
@@ -420,8 +422,6 @@ void CL_RelinkEntities (void)
        vec3_t          delta;
        float           bobjrotate;
        vec3_t          oldorg;
-       dlight_t        *dl;
-       byte            *tempcolor;
 
 // determine partial update time       
        frac = CL_LerpPoint ();
@@ -481,7 +481,7 @@ void CL_RelinkEntities (void)
                else
                {       // if the delta is large, assume a teleport and don't lerp
                        f = frac;
-                       for (j=0 ; j<3 ; j++)
+                       for (j = 0;j < 3;j++)
                        {
                                delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j];
                                // LordHavoc: increased lerp tolerance from 100 to 200
@@ -490,7 +490,7 @@ void CL_RelinkEntities (void)
                        }
 
                // interpolate the origin and angles
-                       for (j=0 ; j<3 ; j++)
+                       for (j = 0;j < 3;j++)
                        {
                                ent->origin[j] = ent->msg_origins[1][j] + f*delta[j];
 
@@ -508,63 +508,30 @@ void CL_RelinkEntities (void)
                        R_EntityParticles (ent);
                if (ent->effects & EF_MUZZLEFLASH)
                {
-                       vec3_t          fv;
-
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin,  dl->origin);
-                       dl->origin[2] += 16;
-                       AngleVectors (ent->angles, fv, NULL, NULL);
-                        
-                       VectorMA (dl->origin, 18, fv, dl->origin);
-                       dl->radius = 100 + (rand()&31);
-                       dl->die = cl.time + 0.1;
-                       dl->color[0] = 1.0;dl->color[1] = 1.0;dl->color[2] = 1.0;
+                       vec3_t v;
+
+                       AngleVectors (ent->angles, v, NULL, NULL);
+
+                       v[0] = v[0] * 18 + ent->origin[0];
+                       v[1] = v[1] * 18 + ent->origin[1];
+                       v[2] = v[2] * 18 + ent->origin[2] + 16;
+
+                       CL_AllocDlight (ent, v, 100, 1, 1, 1, 0, 0.1);
                }
                if (ent->effects & EF_BRIGHTLIGHT)
-               {                       
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin,  dl->origin);
-                       dl->origin[2] += 16;
-                       dl->radius = 400 + (rand()&31);
-                       dl->die = cl.time + 0.001;
-                       dl->color[0] = 1.0;dl->color[1] = 1.0;dl->color[2] = 1.0;
-               }
+                       CL_AllocDlight (ent, ent->origin, 400, 1, 1, 1, 0, 0);
                if (ent->effects & EF_DIMLIGHT)
-               {                       
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin,  dl->origin);
-                       dl->radius = 200 + (rand()&31);
-                       dl->die = cl.time + 0.001;
-                       dl->color[0] = 1.0;dl->color[1] = 1.0;dl->color[2] = 1.0;
-               }
+                       CL_AllocDlight (ent, ent->origin, 200, 1, 1, 1, 0, 0);
                // LordHavoc: added EF_RED and EF_BLUE
                if (ent->effects & EF_RED) // red
                {                       
                        if (ent->effects & EF_BLUE) // magenta
-                       {
-                               dl = CL_AllocDlight (i);
-                               VectorCopy (ent->origin,  dl->origin);
-                               dl->radius = 200 + (rand()&31);
-                               dl->die = cl.time + 0.001;
-                               dl->color[0] = 0.7;dl->color[1] = 0.07;dl->color[2] = 0.7;
-                       }
+                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.2f, 1.0f, 0, 0);
                        else // red
-                       {
-                               dl = CL_AllocDlight (i);
-                               VectorCopy (ent->origin,  dl->origin);
-                               dl->radius = 200 + (rand()&31);
-                               dl->die = cl.time + 0.001;
-                               dl->color[0] = 0.8;dl->color[1] = 0.05;dl->color[2] = 0.05;
-                       }
+                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.1f, 0.1f, 0, 0);
                }
                else if (ent->effects & EF_BLUE) // blue
-               {
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin,  dl->origin);
-                       dl->radius = 200 + (rand()&31);
-                       dl->die = cl.time + 0.001;
-                       dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
-               }
+                       CL_AllocDlight (ent, ent->origin, 200, 0.1f, 0.1f, 1.0f, 0, 0);
                else if (ent->effects & EF_FLAME)
                {
                        if (ent->model)
@@ -574,15 +541,10 @@ void CL_RelinkEntities (void)
                                VectorAdd(ent->origin, ent->model->mins, mins);
                                VectorAdd(ent->origin, ent->model->maxs, maxs);
                                // how many flames to make
-                               temp = (int) (cl.time * 30) - (int) (cl.oldtime * 30);
+                               temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300);
                                R_FlameCube(mins, maxs, temp);
                        }
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin, dl->origin);
-                       dl->radius = 200 + (rand()&31);
-                       dl->die = cl.time + 0.25;
-                       dl->decay = dl->radius * 4;
-                       dl->color[0] = 1.0;dl->color[1] = 0.7;dl->color[2] = 0.3;
+                       CL_AllocDlight (ent, ent->origin, lhrandom(200, 250), 1.0f, 0.7f, 0.3f, 0, 0);
                }
 
                if (ent->model->flags) // LordHavoc: if the model has no flags, don't check each
@@ -601,11 +563,7 @@ void CL_RelinkEntities (void)
                        else if (ent->model->flags & EF_ROCKET)
                        {
                                R_RocketTrail (oldorg, ent->origin, 0, ent);
-                               dl = CL_AllocDlight (i);
-                               VectorCopy (ent->origin, dl->origin);
-                               dl->radius = 200;
-                               dl->die = cl.time + 0.001;
-                               dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
+                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.8f, 0.4f, 0, 0);
                        }
                        else if (ent->model->flags & EF_GRENADE)
                        {
@@ -619,12 +577,8 @@ void CL_RelinkEntities (void)
                }
                if (ent->glowsize) // LordHavoc: customizable glow
                {
-                       dl = CL_AllocDlight (i);
-                       VectorCopy (ent->origin, dl->origin);
-                       dl->radius = ent->glowsize;
-                       dl->die = cl.time + 0.001;
-                       tempcolor = (byte *)&d_8to24table[ent->glowcolor];
-                       dl->color[0] = tempcolor[0]*(1.0/255.0);dl->color[1] = tempcolor[1]*(1.0/255.0);dl->color[2] = tempcolor[2]*(1.0/255.0);
+                       byte *tempcolor = (byte *)&d_8to24table[ent->glowcolor];
+                       CL_AllocDlight (ent, ent->origin, ent->glowsize, tempcolor[0]*(1.0/255.0), tempcolor[1]*(1.0/255.0), tempcolor[2]*(1.0/255.0), 0, 0);
                }
                if (ent->glowtrail) // LordHavoc: customizable glow and trail
                        R_RocketTrail2 (oldorg, ent->origin, ent->glowcolor, ent);
@@ -640,10 +594,12 @@ void CL_RelinkEntities (void)
                if (cl_numvisedicts < MAX_VISEDICTS)
                        cl_visedicts[cl_numvisedicts++] = ent;
        }
-
 }
 
 
+// used by cl_shownet
+int netshown;
+
 /*
 ===============
 CL_ReadFromServer
@@ -658,6 +614,7 @@ int CL_ReadFromServer (void)
        cl.oldtime = cl.time;
        cl.time += cl.frametime;
        
+       netshown = false;
        do
        {
                ret = CL_GetMessage ();
@@ -670,7 +627,7 @@ int CL_ReadFromServer (void)
                CL_ParseServerMessage ();
        } while (ret && cls.state == ca_connected);
        
-       if (cl_shownet.value)
+       if (netshown)
                Con_Printf ("\n");
 
        CL_RelinkEntities ();
index 368bf3da43efdc6e8628c7b387ece1ca9e9957ba..d856ce119268b9fbeb21e7262595e7b80583aea6 100644 (file)
@@ -822,6 +822,7 @@ void CL_ParseEffect2 (void)
 extern void SHOWLMP_decodehide();
 extern void SHOWLMP_decodeshow();
 extern void R_SetSkyBox(char* sky);
+extern int netshown;
 
 /*
 =====================
@@ -840,9 +841,15 @@ void CL_ParseServerMessage (void)
 // if recording demos, copy the message out
 //
        if (cl_shownet.value == 1)
+       {
                Con_Printf ("%i ",net_message.cursize);
+               netshown = true;
+       }
        else if (cl_shownet.value == 2)
+       {
                Con_Printf ("------------------\n");
+               netshown = true;
+       }
        
        cl.onground = false;    // unless the server says otherwise     
 //
index 1046cbc66337345d721392b9bfac6b4e2f2b7175..363ca591d70db5bf27a9381738dd36f311da8610 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -127,10 +127,9 @@ void CL_ParseTEnt (void)
        vec3_t  pos;
        vec3_t  dir;
        vec3_t  pos2;
-       dlight_t        *dl;
        int             rnd;
        int             colorStart, colorLength, count;
-       float   velspeed;
+       float   velspeed, radius;
        byte *tempcolor;
 
        type = MSG_ReadByte ();
@@ -171,12 +170,7 @@ void CL_ParseTEnt (void)
                // LordHavoc: changed to spark shower
                R_SparkShower(pos, vec3_origin, 15);
                //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_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);
@@ -214,12 +208,7 @@ void CL_ParseTEnt (void)
                // LordHavoc: changed to dust shower
                R_SparkShower(pos, vec3_origin, 30);
                //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_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
@@ -301,12 +290,7 @@ void CL_ParseTEnt (void)
        case TE_GUNSHOTQUAD:                    // quad bullet hitting wall
                MSG_ReadVector(pos);
                R_SparkShower(pos, vec3_origin, 15);
-               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_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                break;
 
        case TE_EXPLOSION:                      // rocket explosion
@@ -314,12 +298,7 @@ void CL_ParseTEnt (void)
                FindNonSolidLocation(pos);
                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;
+               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;
 
@@ -328,12 +307,7 @@ void CL_ParseTEnt (void)
                FindNonSolidLocation(pos);
                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;
+               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;
 
@@ -342,12 +316,7 @@ void CL_ParseTEnt (void)
                MSG_ReadVector(pos);
                FindNonSolidLocation(pos);
                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;
+               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;
                */
@@ -357,12 +326,7 @@ void CL_ParseTEnt (void)
                FindNonSolidLocation(pos);
                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();
+               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;
 
@@ -371,12 +335,7 @@ void CL_ParseTEnt (void)
                FindNonSolidLocation(pos);
                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);
+               CL_AllocDlight (NULL, pos, 350, MSG_ReadByte() * (1.0 / 255.0), MSG_ReadByte() * (1.0 / 255.0), MSG_ReadByte() * (1.0 / 255.0), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
@@ -387,36 +346,22 @@ void CL_ParseTEnt (void)
 //             R_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);
                FindNonSolidLocation(pos);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = 200;
-               dl->die = cl.time + 0.2;
-               dl->decay = 1000;
-               dl->color[0] = dl->color[1] = dl->color[2] = 1;
+               CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
                break;
 
        case TE_CUSTOMFLASH:
                MSG_ReadVector(pos);
                FindNonSolidLocation(pos);
-               dl = CL_AllocDlight (0);
-               VectorCopy (pos, dl->origin);
-               dl->radius = MSG_ReadByte() * 8;
+               radius = MSG_ReadByte() * 8;
                velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
-               dl->die = cl.time + velspeed;
-               dl->decay = dl->radius / velspeed;
-               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);
+               CL_AllocDlight (NULL, pos, radius, MSG_ReadByte() * (1.0 / 255.0), MSG_ReadByte() * (1.0 / 255.0), MSG_ReadByte() * (1.0 / 255.0), radius / velspeed, velspeed);
                break;
 
        case TE_FLAMEJET:
@@ -470,13 +415,8 @@ void CL_ParseTEnt (void)
                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;
                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;
                
@@ -525,7 +465,6 @@ void CL_UpdateTEnts (void)
        entity_t        *ent;
        float           yaw, pitch;
        float           forward;
-       dlight_t        *dl;
 
        num_temp_entities = 0;
 
@@ -579,20 +518,14 @@ void CL_UpdateTEnts (void)
                        ent->angles[1] = yaw;
                        ent->angles[2] = rand()%360;
 
-                       if (r_glowinglightning.value)
-                       {
-                               dl = CL_AllocDlight (0);
-                               VectorCopy (ent->origin,  dl->origin);
-                               dl->radius = 100 + (rand()&31);
-                               dl->die = cl.time + 0.001;
-                               dl->color[0] = dl->color[1] = dl->color[2] = r_glowinglightning.value * 0.25f;
-                       }
+                       if (r_glowinglightning.value > 0)
+                               CL_AllocDlight(ent, ent->origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0);
 
                        VectorMA(org, 30, dist, org);
                        d -= 30;
                }
        }
-       
+
 }
 
 
index 9abe25e25db9fa00d82a4ac196c90a60fdb80dcc..f7aa2af01e3519275146367beaf504606b280fc5 100644 (file)
--- a/client.h
+++ b/client.h
@@ -40,8 +40,7 @@ typedef struct
        char    name[MAX_SCOREBOARDNAME];
        float   entertime;
        int             frags;
-       int             colors;                 // two 4 bit fields
-//     byte    translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
+       int             colors; // two 4 bit fields
 } scoreboard_t;
 
 typedef struct
@@ -74,7 +73,8 @@ typedef struct
        struct model_s  *model;
        float   endtime;
        vec3_t  start, end;
-} beam_t;
+}
+beam_t;
 
 // LordHavoc: increased MAX_EFRAGS from 640 to 2048
 #define        MAX_EFRAGS              2048
@@ -83,11 +83,13 @@ typedef struct
 #define        MAX_DEMOS               8
 #define        MAX_DEMONAME    16
 
-typedef enum {
-ca_dedicated,          // a dedicated server with no ability to start a client
-ca_disconnected,       // full screen console with no connection
-ca_connected           // valid netcon, talking to a server
-} cactive_t;
+typedef enum
+{
+       ca_dedicated,           // a dedicated server with no ability to start a client
+       ca_disconnected,        // full screen console with no connection
+       ca_connected            // valid netcon, talking to a server
+}
+cactive_t;
 
 //
 // the client_static_t structure is persistant through an arbitrary number
@@ -122,8 +124,8 @@ typedef struct
        int                     signon;                 // 0 to SIGNONS
        struct qsocket_s        *netcon;
        sizebuf_t       message;                // writing buffer to send to server
-       
-client_static_t;
+}
+client_static_t;
 
 extern client_static_t cls;
 
@@ -162,7 +164,7 @@ typedef struct
 
        vec3_t          punchangle;             // temporary offset
        vec3_t          punchvector;    // LordHavoc: origin view kick
-       
+
 // pitch drifting vars
        float           idealpitch;
        float           pitchvel;
@@ -176,10 +178,10 @@ typedef struct
        qboolean        paused;                 // send over by server
        qboolean        onground;
        qboolean        inwater;
-       
+
        int                     intermission;   // don't change view angle, full screen, etc
        int                     completed_time; // latched at intermission start
-       
+
        double          mtime[2];               // the timestamp of last two messages   
        double          time;                   // clients view of time, should be between
                                                                // servertime and oldservertime to generate
@@ -188,7 +190,7 @@ typedef struct
                                                                // to decay light values and smooth step ups
 
        double          frametime;
-       
+
 
        float           last_received_message;  // (realtime) for net trouble icon
 
@@ -214,7 +216,8 @@ typedef struct
 
 // frag scoreboard
        scoreboard_t    *scores;                // [cl.maxclients]
-} client_state_t;
+}
+client_state_t;
 
 
 //
@@ -272,8 +275,8 @@ extern      beam_t                  cl_beams[MAX_BEAMS];
 //
 // cl_main
 //
-dlight_t *CL_AllocDlight (int key);
-void   CL_DecayLights (void);
+void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime);
+void CL_DecayLights (void);
 
 void CL_Init (void);
 
@@ -288,9 +291,9 @@ void CL_Disconnect_f (void);
 void CL_NextDemo (void);
 
 // LordHavoc: raised this from 256 to the maximum possible number of entities visible
-#define                        MAX_VISEDICTS   (MAX_EDICTS + MAX_STATIC_ENTITIES + MAX_TEMP_ENTITIES)
-extern int                             cl_numvisedicts;
-extern entity_t                *cl_visedicts[MAX_VISEDICTS];
+#define MAX_VISEDICTS (MAX_EDICTS + MAX_STATIC_ENTITIES + MAX_TEMP_ENTITIES)
+extern int                     cl_numvisedicts;
+extern entity_t        *cl_visedicts[MAX_VISEDICTS];
 
 //
 // cl_input
@@ -299,7 +302,8 @@ typedef struct
 {
        int             down[2];                // key nums holding it down
        int             state;                  // low bit is down state
-} kbutton_t;
+}
+kbutton_t;
 
 extern kbutton_t       in_mlook, in_klook;
 extern         kbutton_t       in_strafe;
index 93622b14e4530f6f8f8223223bd79dfeda4353b3..3425daf84dca34e94bb7881c1d1939d109176214 100644 (file)
@@ -17,7 +17,7 @@ void fractalnoise(byte *noise, int size, int startgrid)
 
        startgrid = bound(0, startgrid, size);
 
-       amplitude = 32767;
+       amplitude = 0xFFFF; // this gets halved before use
        noisebuf = qmalloc(size*size*sizeof(int));
        memset(noisebuf, 0, size*size*sizeof(int));
 
@@ -55,10 +55,11 @@ void fractalnoise(byte *noise, int size, int startgrid)
                        if (n(x,y) > max) max = n(x,y);
                }
        max -= min;
+       max++;
        // normalize noise and copy to output
        for (y = 0;y < size;y++)
                for (x = 0;x < size;x++)
-                       *noise++ = (n(x,y) - min) * 255 / max;
+                       *noise++ = (byte) (((n(x,y) - min) * 256) / max);
        qfree(noisebuf);
 #undef n
 }
index f2c94651bde91ce59c5841748f6d4f0a8b53d23b..5a348d3e80544fb2696a761b2d91af6910ffb1eb 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -154,6 +154,10 @@ void gl_draw_shutdown()
 {
 }
 
+void gl_draw_newmap()
+{
+}
+
 char engineversion[40];
 int engineversionx, engineversiony;
 
@@ -178,7 +182,7 @@ void GL_Draw_Init (void)
        engineversiony = vid.height - 8;
 
        R_Textures_Init();
-       R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown);
+       R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
 }
 
 /*
index 99e71140dc247f300bd1ccae99cbb4c916ffc5d5..6065452e02e9b031d38eb3c52af4b8c8c0e6c4bc 100644 (file)
@@ -92,12 +92,16 @@ void gl_models_shutdown()
        qfree(aliasvertusage);
 }
 
+void gl_models_newmap()
+{
+}
+
 void GL_Models_Init()
 {
        Cvar_RegisterVariable(&gl_transform);
        Cvar_RegisterVariable(&gl_lockarrays);
 
-       R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
+       R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
 }
 
 extern vec3_t softwaretransform_x;
@@ -318,7 +322,7 @@ R_DrawAliasFrame
 =================
 */
 extern vec3_t lightspot;
-void R_LightModel(int numverts, vec3_t center, vec3_t basecolor);
+void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor);
 void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t **skin, int colormap, int effects, int flags)
 {
        if (gl_transform.value)
@@ -350,7 +354,7 @@ void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity
                GL_LockArray(0, maliashdr->numverts);
        }
 
-       R_LightModel(maliashdr->numverts, org, color);
+       R_LightModel(ent, maliashdr->numverts, org, color);
 
        if (!r_render.value)
                return;
@@ -473,7 +477,7 @@ void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t
        if (!gl_transform.value)
                R_AliasTransformVerts(pheader->num_xyz);
 
-       R_LightModel(pheader->num_xyz, org, color);
+       R_LightModel(ent, pheader->num_xyz, org, color);
 
        if (!r_render.value)
                return;
@@ -895,7 +899,7 @@ void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_
        ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
        ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
 
-       R_LightModel(m->numverts, org, color);
+       R_LightModel(ent, m->numverts, org, color);
 
        if (!r_render.value)
                return;
@@ -929,8 +933,6 @@ void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_
        glDepthMask(1);
 }
 
-extern int r_dlightframecount;
-
 /*
 =================
 R_DrawAliasModel
index 4eb8bafebd634f45516b7953cd7e6a401914dc4e..d2114ab609e0d1eaa3b99767b640916bf9f7da64 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -49,6 +49,7 @@ void gl_poly_start()
        for (i = 1;i < 256;i++)
                transreciptable[i] = 1.0f / i;
 }
+
 void gl_poly_shutdown()
 {
        qfree(transvert);
@@ -61,10 +62,14 @@ void gl_poly_shutdown()
        qfree(skypoly);
 }
 
+void gl_poly_newmap()
+{
+}
+
 void GL_Poly_Init()
 {
        Cvar_RegisterVariable (&gl_multitexture);
-       R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown);
+       R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown, gl_poly_newmap);
 }
 
 void transpolyclear()
@@ -786,7 +791,7 @@ extern char skyname[];
 extern rtexture_t *solidskytexture, *alphaskytexture;
 void skypolyrender()
 {
-       int i, j, numskyverts;
+       int i, j;
        skypoly_t *p;
        skyvert_t *vert;
        float length, speedscale;
@@ -805,9 +810,9 @@ void skypolyrender()
        if (!fogenabled && !skyname[0]) // normal quake sky
        {
                glInterleavedArrays(GL_T2F_V3F, 0, skyvert);
-//             glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 2, &skyvert[0].tex[0]);
+//             glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].tex[0]);
 //             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-//             glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]);
+//             glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].v[0]);
 //             glEnableClientState(GL_VERTEX_ARRAY);
                if(lighthalf)
                        glColor3f(0.5f, 0.5f, 0.5f);
@@ -820,7 +825,6 @@ void skypolyrender()
                glBindTexture(GL_TEXTURE_2D, R_GetTexture(solidskytexture)); // upper clouds
                speedscale = cl.time*8;
                speedscale -= (int)speedscale & ~127 ;
-               numskyverts = 0;
                for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                {
                        vert = skyvert + p->firstvert;
@@ -836,9 +840,8 @@ void skypolyrender()
                                vert->tex[0] = (speedscale + dir[0] * length) * (1.0/128);
                                vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128);
                        }
-                       numskyverts += p->verts;
                }
-               GL_LockArray(0, numskyverts);
+               GL_LockArray(0, currentskyvert);
                for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                        glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                GL_UnlockArray();
@@ -863,7 +866,7 @@ void skypolyrender()
                                vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128);
                        }
                }
-               GL_LockArray(0, numskyverts);
+               GL_LockArray(0, currentskyvert);
                for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                        glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                GL_UnlockArray();
@@ -875,15 +878,12 @@ void skypolyrender()
        }
        else
        {
-               glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]);
+               glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].v[0]);
                glEnableClientState(GL_VERTEX_ARRAY);
                glDisable(GL_TEXTURE_2D);
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                glColor3fv(fogcolor); // note: gets rendered over by skybox if fog is not enabled
-               numskyverts = 0;
-               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
-                       numskyverts += p->verts;
-               GL_LockArray(0, numskyverts);
+               GL_LockArray(0, currentskyvert);
                for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                        glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                GL_UnlockArray();
index 24ece5f538c18ffbc004ce717fe7f4cb8546f770..25747e9ae118b003a6ab94cc7317fcf7b66c9c18 100644 (file)
--- a/gl_poly.h
+++ b/gl_poly.h
@@ -18,7 +18,7 @@ extern void skypolybegin();
 extern void skypolyvert(float x, float y, float z);
 extern void skypolyend();
 
-#define MAX_TRANSPOLYS 8192
+#define MAX_TRANSPOLYS 65536
 #define MAX_TRANSVERTS (MAX_TRANSPOLYS*4)
 #define MAX_WALLPOLYS 65536
 #define MAX_WALLVERTS (MAX_WALLPOLYS*3)
index c4a257d239f4016a08b00ae0b56c65e1730a3361..f3806a332ca76daabd5dfedb10447c3fd6e8a335 100644 (file)
@@ -211,11 +211,15 @@ void FOG_registercvars()
        }
 }
 
-void glmain_start()
+void gl_main_start()
 {
 }
 
-void glmain_shutdown()
+void gl_main_shutdown()
+{
+}
+
+void gl_main_newmap()
 {
 }
 
@@ -241,7 +245,7 @@ void GL_Main_Init()
 //     if (gl_vendor && strstr(gl_vendor, "3Dfx"))
 //             gl_lightmode.value = 0;
        Cvar_RegisterVariable (&r_fullbright);
-       R_RegisterModule("GL_Main", glmain_start, glmain_shutdown);
+       R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
 }
 
 extern void GL_Draw_Init();
@@ -259,7 +263,7 @@ extern void CL_Effects_Init();
 
 void Render_Init()
 {
-       R_ShutdownModules();
+       R_Modules_Shutdown();
        GL_Draw_Init();
        GL_Main_Init();
        GL_Models_Init();
@@ -272,7 +276,8 @@ void Render_Init()
        R_Particles_Init();
        R_Explosion_Init();
        CL_Effects_Init();
-       R_StartModules();
+       R_Decals_Init();
+       R_Modules_Start();
 }
 
 /*
@@ -739,16 +744,6 @@ void GL_BlendView()
        glEnable(GL_TEXTURE_2D);
 }
 
-/*
-#define TIMEREPORT(DESC) \
-       if (r_speeds2.value)\
-       {\
-               temptime = -currtime;\
-               currtime = Sys_FloatTime();\
-               temptime += currtime;\
-               Con_Printf(DESC " %.4fms ", temptime * 1000.0);\
-       }
-*/
 #define TIMEREPORT(VAR) \
        if (r_speeds2.value)\
        {\
@@ -770,12 +765,11 @@ extern qboolean intimerefresh;
 extern qboolean skyisvisible;
 extern void R_Sky();
 extern void UploadLightmaps();
-char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81];
+char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81];
 void R_RenderView (void)
 {
        double starttime, currtime, temptime;
-       int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_moveexplosions, time_drawexplosions, time_transpoly, time_blend, time_total;
-//     double currtime, temptime;
+       int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend, time_total;
 //     if (r_norefresh.value)
 //             return;
 
@@ -789,7 +783,6 @@ void R_RenderView (void)
        if (r_speeds2.value)
        {
                starttime = currtime = Sys_FloatTime();
-//             Con_Printf("render time: ");
        }
        else
                starttime = currtime = 0;
@@ -842,6 +835,8 @@ void R_RenderView (void)
        TIMEREPORT(time_moveexplosions)
        R_DrawExplosions();
        TIMEREPORT(time_drawexplosions)
+       R_DrawDecals();
+       TIMEREPORT(time_drawdecals)
 
        transpolyrender();
        TIMEREPORT(time_transpoly)
@@ -853,12 +848,12 @@ void R_RenderView (void)
        if (r_speeds2.value)
        {
                time_total = (int) ((Sys_FloatTime() - starttime) * 1000000.0);
-//             Con_Printf("\n");
                sprintf(r_speeds2_string1, "%6i walls %6i dlitwalls %7i modeltris %7i transpoly\n", c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly);
                sprintf(r_speeds2_string2, "BSP: %6i faces %6i nodes %6i leafs\n", c_faces, c_nodes, c_leafs);
                sprintf(r_speeds2_string3, "%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights);
                sprintf(r_speeds2_string4, "%6ius clear  %6ius setup  %6ius world  %6ius bmodel %6ius upload", time_clear, time_setup, time_world, time_bmodels, time_upload);
                sprintf(r_speeds2_string5, "%6ius sky    %6ius wall   %6ius models %6ius mpart  %6ius dpart ", time_sky, time_wall, time_models, time_moveparticles, time_drawparticles);
-               sprintf(r_speeds2_string6, "%6ius trans  %6ius blend  %6ius total  %6ius permdl", time_transpoly, time_blend, time_total, time_models / max(c_models, 1));
+               sprintf(r_speeds2_string6, "%6ius mexplo %6ius dexplo %6ius decals %6ius trans  %6ius blend ", time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend);
+               sprintf(r_speeds2_string7, "%6ius permdl %6ius total ", time_models / max(c_models, 1), time_total);
        }
 }
index c5c367d6a9e602220b9c60ea23fa1dc44748f78e..72dc5e4355036dc81c21cad58a159335c31a814f 100644 (file)
@@ -136,6 +136,10 @@ void gl_misc_shutdown()
 {
 }
 
+void gl_misc_newmap()
+{
+}
+
 /*
 ===============
 R_Init
@@ -146,7 +150,7 @@ void GL_Misc_Init (void)
        Cmd_AddCommand ("envmap", R_Envmap_f);  
        Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);        
 
-       R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown);
+       R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown, gl_misc_newmap);
 }
 
 void R_ClearParticles (void);
@@ -175,7 +179,7 @@ void R_NewMap (void)
                cl.worldmodel->leafs[i].efrags = NULL;
                        
        r_viewleaf = NULL;
-       R_ClearParticles ();
+       R_Modules_NewMap();
 
        GL_BuildLightmaps ();
 
index 026861df783f77b0a203c3f973ec1252f84108fb..b19aa685a1e696373e37655ad25f0df221b5de88 100644 (file)
@@ -378,6 +378,10 @@ void gl_screen_shutdown()
 {
 }
 
+void gl_screen_newmap()
+{
+}
+
 /*
 ==================
 SCR_Init
@@ -409,7 +413,7 @@ void GL_Screen_Init (void)
 
        scr_initialized = true;
 
-       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown);
+       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown, gl_screen_newmap);
 }
 
 
@@ -940,13 +944,14 @@ void SCR_UpdateScreen (void)
 
        if (r_speeds2.value)
        {
-               extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81];
-               Draw_String(0, vid.height - sb_lines - 48, r_speeds2_string1, 80);
-               Draw_String(0, vid.height - sb_lines - 40, r_speeds2_string2, 80);
-               Draw_String(0, vid.height - sb_lines - 32, r_speeds2_string3, 80);
-               Draw_String(0, vid.height - sb_lines - 24, r_speeds2_string4, 80);
-               Draw_String(0, vid.height - sb_lines - 16, r_speeds2_string5, 80);
-               Draw_String(0, vid.height - sb_lines -  8, r_speeds2_string6, 80);
+               extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81];
+               Draw_String(0, vid.height - sb_lines - 56, r_speeds2_string1, 80);
+               Draw_String(0, vid.height - sb_lines - 48, r_speeds2_string2, 80);
+               Draw_String(0, vid.height - sb_lines - 40, r_speeds2_string3, 80);
+               Draw_String(0, vid.height - sb_lines - 32, r_speeds2_string4, 80);
+               Draw_String(0, vid.height - sb_lines - 24, r_speeds2_string5, 80);
+               Draw_String(0, vid.height - sb_lines - 16, r_speeds2_string6, 80);
+               Draw_String(0, vid.height - sb_lines -  8, r_speeds2_string7, 80);
        }
 
        V_UpdateBlends ();
index a5644a3d5c5645e85e5982aa56d50e453687376b..6248f5bcf120980d17b40f7071ed870035132eaa 100644 (file)
@@ -169,6 +169,10 @@ void r_textures_shutdown()
 {
 }
 
+void r_textures_newmap()
+{
+}
+
 void R_Textures_Init (void)
 {
        Cmd_AddCommand("r_texturestats", GL_TextureStats_f);
@@ -189,7 +193,7 @@ void R_Textures_Init (void)
        memset(gltextures, 0, sizeof(gltexture_t) * MAX_GLTEXTURES);
        Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
 
-       R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown);
+       R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap);
 }
 
 /*
@@ -213,7 +217,7 @@ int R_FindTexture (char *identifier)
 
 void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
 {
-       int             j, xi, oldx = 0, f, fstep, l1, l2, endx;
+       int             j, xi, oldx = 0, f, fstep, endx;
        fstep = (int) (inwidth*65536.0f/outwidth);
        endx = (inwidth-1);
        for (j = 0,f = 0;j < outwidth;j++, f += fstep)
@@ -226,12 +230,11 @@ void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
                }
                if (xi < endx)
                {
-                       l2 = f & 0xFFFF;
-                       l1 = 0x10000 - l2;
-                       *out++ = (byte) ((in[0] * l1 + in[4] * l2) >> 16);
-                       *out++ = (byte) ((in[1] * l1 + in[5] * l2) >> 16);
-                       *out++ = (byte) ((in[2] * l1 + in[6] * l2) >> 16);
-                       *out++ = (byte) ((in[3] * l1 + in[7] * l2) >> 16);
+                       int lerp = f & 0xFFFF;
+                       *out++ = (byte) ((((in[4] - in[0]) * lerp) >> 16) + in[0]);
+                       *out++ = (byte) ((((in[5] - in[1]) * lerp) >> 16) + in[1]);
+                       *out++ = (byte) ((((in[6] - in[2]) * lerp) >> 16) + in[2]);
+                       *out++ = (byte) ((((in[7] - in[3]) * lerp) >> 16) + in[3]);
                }
                else // last pixel of the line has no pixel to lerp to
                {
@@ -250,9 +253,12 @@ R_ResampleTexture
 */
 void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight)
 {
+       if (outwidth & 3)
+               Sys_Error("R_ResampleTexture: output width must be a multiple of 4");
+
        if (r_lerpimages.value)
        {
-               int             i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
+               int             i, j, yi, oldy, f, fstep, endy = (inheight-1);
                byte    *inrow, *out, *row1, *row2;
                out = outdata;
                fstep = (int) (inheight*65536.0f/outheight);
@@ -266,43 +272,56 @@ void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,
                for (i = 0, f = 0;i < outheight;i++,f += fstep)
                {
                        yi = f >> 16;
-                       if (yi != oldy)
-                       {
-                               inrow = (byte *)indata + inwidth*4*yi;
-                               if (yi == oldy+1)
-                                       memcpy(row1, row2, outwidth*4);
-                               else
-                                       R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
-                               if (yi < endy)
-                                       R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
-                               else
-                                       memcpy(row2, row1, outwidth*4);
-                               oldy = yi;
-                       }
                        if (yi < endy)
                        {
-                               l2 = f & 0xFFFF;
-                               l1 = 0x10000 - l2;
-                               for (j = 0;j < outwidth;j++)
+                               int lerp = f & 0xFFFF;
+                               if (yi != oldy)
                                {
-                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
-                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
-                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
-                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+                                       inrow = (byte *)indata + inwidth*4*yi;
+                                       if (yi == oldy+1)
+                                               memcpy(row1, row2, outwidth*4);
+                                       else
+                                               R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+                                       R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+                                       oldy = yi;
+                               }
+                               for (j = 0;j < outwidth;j += 4)
+                               {
+                                       out[ 0] = (byte) ((((row2[ 0] - row1[ 0]) * lerp) >> 16) + row1[ 0]);
+                                       out[ 1] = (byte) ((((row2[ 1] - row1[ 1]) * lerp) >> 16) + row1[ 1]);
+                                       out[ 2] = (byte) ((((row2[ 2] - row1[ 2]) * lerp) >> 16) + row1[ 2]);
+                                       out[ 3] = (byte) ((((row2[ 3] - row1[ 3]) * lerp) >> 16) + row1[ 3]);
+                                       out[ 4] = (byte) ((((row2[ 4] - row1[ 4]) * lerp) >> 16) + row1[ 4]);
+                                       out[ 5] = (byte) ((((row2[ 5] - row1[ 5]) * lerp) >> 16) + row1[ 5]);
+                                       out[ 6] = (byte) ((((row2[ 6] - row1[ 6]) * lerp) >> 16) + row1[ 6]);
+                                       out[ 7] = (byte) ((((row2[ 7] - row1[ 7]) * lerp) >> 16) + row1[ 7]);
+                                       out[ 8] = (byte) ((((row2[ 8] - row1[ 8]) * lerp) >> 16) + row1[ 8]);
+                                       out[ 9] = (byte) ((((row2[ 9] - row1[ 9]) * lerp) >> 16) + row1[ 9]);
+                                       out[10] = (byte) ((((row2[10] - row1[10]) * lerp) >> 16) + row1[10]);
+                                       out[11] = (byte) ((((row2[11] - row1[11]) * lerp) >> 16) + row1[11]);
+                                       out[12] = (byte) ((((row2[12] - row1[12]) * lerp) >> 16) + row1[12]);
+                                       out[13] = (byte) ((((row2[13] - row1[13]) * lerp) >> 16) + row1[13]);
+                                       out[14] = (byte) ((((row2[14] - row1[14]) * lerp) >> 16) + row1[14]);
+                                       out[15] = (byte) ((((row2[15] - row1[15]) * lerp) >> 16) + row1[15]);
+                                       out += 16;
+                                       row1 += 16;
+                                       row2 += 16;
                                }
                                row1 -= outwidth*4;
                                row2 -= outwidth*4;
                        }
-                       else // last line has no pixels to lerp to
+                       else
                        {
-                               for (j = 0;j < outwidth;j++)
+                               if (yi != oldy)
                                {
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
+                                       inrow = (byte *)indata + inwidth*4*yi;
+                                       if (yi == oldy+1)
+                                               memcpy(row1, row2, outwidth*4);
+                                       else
+                                               R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+                                       oldy = yi;
                                }
-                               row1 -= outwidth*4;
+                               memcpy(out, row1, outwidth * 4);
                        }
                }
                qfree(row1);
@@ -310,22 +329,24 @@ void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,
        }
        else
        {
-               int             i, j;
-               unsigned        frac, fracstep;
-               byte    *inrow, *out, *inpix;
+               int i, j;
+               unsigned frac, fracstep;
+               // relies on int being 4 bytes
+               int *inrow, *out;
                out = outdata;
 
                fracstep = inwidth*0x10000/outwidth;
-               for (i=0 ; i<outheight ; i++)
+               for (i = 0;i < outheight;i++)
                {
-                       inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
+                       inrow = (int *)indata + inwidth*(i*inheight/outheight);
                        frac = fracstep >> 1;
-                       for (j=0 ; j<outwidth ; j+=4)
+                       for (j = 0;j < outwidth;j += 4)
                        {
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
+                               out[0] = inrow[frac >> 16];frac += fracstep;
+                               out[1] = inrow[frac >> 16];frac += fracstep;
+                               out[2] = inrow[frac >> 16];frac += fracstep;
+                               out[3] = inrow[frac >> 16];frac += fracstep;
+                               out += 4;
                        }
                }
        }
diff --git a/host.c b/host.c
index 3d687b6d0a224a91d335e7e4e07217c2af33d126..7c165adbd9d73ee5228ab6d69971308cefdf2794 100644 (file)
--- a/host.c
+++ b/host.c
@@ -827,6 +827,7 @@ Host_Init
 */
 void Host_Init ()
 {
+       int i;
        /*
        if (standard_quake)
                minimum_memory = MINIMUM_MEMORY;
@@ -840,6 +841,24 @@ void Host_Init ()
                Sys_Error ("Only %4.1f megs of memory available, can't execute game", host_parms.memsize / (float)0x100000);
        */
 
+       host_parms.memsize = DEFAULTMEM * 1024 * 1024;
+
+       i = COM_CheckParm("-mem");
+       if (i)
+               host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024 * 1024);
+
+       i = COM_CheckParm("-winmem");
+       if (i)
+               host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024 * 1024);
+
+       i = COM_CheckParm("-heapsize");
+       if (i)
+               host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024);
+
+       host_parms.membase = qmalloc(host_parms.memsize);
+       if (!host_parms.membase)
+               Sys_Error("Not enough memory free, close some programs and try again, or free disk space\n");
+
        com_argc = host_parms.argc;
        com_argv = host_parms.argv;
 
@@ -926,7 +945,7 @@ void Host_Shutdown(void)
 
        if (cls.state != ca_dedicated)
        {
-               R_ShutdownModules();
+               R_Modules_Shutdown();
                VID_Shutdown();
        }
 }
diff --git a/image.c b/image.c
index 7b05a23fc75460c1005d0d1a92f4ee916361fbe0..a26b78fc600f309425b161c5542fe66e8d80e640 100644 (file)
--- a/image.c
+++ b/image.c
@@ -630,3 +630,23 @@ void Image_WriteTGARGBA (char *filename, int width, int height, byte *data)
 
        qfree(buffer);
 }
+
+qboolean Image_CheckAlpha(byte *data, int size, qboolean rgba)
+{
+       byte *end;
+       if (rgba)
+       {
+               // check alpha bytes
+               for (end = data + size * 4, data += 3;data < end;data += 4)
+                       if (*data < 255)
+                               return 1;
+       }
+       else
+       {
+               // color 255 is transparent
+               for (end = data + size;data < end;data++)
+                       if (*data == 255)
+                               return 1;
+       }
+       return 0;
+}
diff --git a/image.h b/image.h
index 60a9759cf0306394f1d80924d988a95572a2e1be..9fc65f0db855bfeb257ff018675dd50594ff2bcc 100644 (file)
--- a/image.h
+++ b/image.h
@@ -1,13 +1,14 @@
 
-extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
-extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
-extern int image_makemask (byte *in, byte *out, int size);
-extern byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
-extern rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
-extern byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight);
-extern rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
-extern rtexture_t *image_masktex;
-extern rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
-extern void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data);
-extern void Image_WriteTGARGB (char *filename, int width, int height, byte *data);
-extern void Image_WriteTGARGBA (char *filename, int width, int height, byte *data);
+void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
+void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
+int image_makemask (byte *in, byte *out, int size);
+byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
+rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight);
+rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+rtexture_t *image_masktex;
+rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data);
+void Image_WriteTGARGB (char *filename, int width, int height, byte *data);
+void Image_WriteTGARGBA (char *filename, int width, int height, byte *data);
+qboolean Image_CheckAlpha(byte *data, int size, qboolean rgba);
index ea8fb19154f49ed0ba95a19e247321d59429ca80..7cbbad778f8a470387b0175da1a2dc57a796a4a3 100644 (file)
--- a/makefile
+++ b/makefile
@@ -7,7 +7,7 @@ SND=snd_alsa_0_9.o
 #if you use the kernel sound driver or OSS
 #SND=snd_oss.o
 
-OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o
+OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o
 
 OPTIMIZATIONS= -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
 
index 33350406d3740fcc3c207eb2542cf73d83e96d1c..8604c43b716e9a283c1d9ee1d0c3a95c2882a7d1 100644 (file)
@@ -224,8 +224,8 @@ void Mod_LoadTextures (lump_t *l)
                        {
                                tx->width = mt->width;
                                tx->height = mt->height;
-                               tx->transparent = true;
-                               tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                               tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
+                               tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
                                tx->glowtexture = NULL;
                        }
                        qfree(data);
@@ -252,8 +252,8 @@ void Mod_LoadTextures (lump_t *l)
                                                {
                                                        tx->width = mt->width;
                                                        tx->height = mt->height;
-                                                       tx->transparent = true;
-                                                       tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->transparent = Image_CheckAlpha(data, mt->width * mt->height, true);
+                                                       tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
                                                        tx->glowtexture = NULL;
                                                        qfree(data);
                                                }
@@ -266,8 +266,8 @@ void Mod_LoadTextures (lump_t *l)
                                                {
                                                        tx->width = image_width;
                                                        tx->height = image_height;
-                                                       tx->transparent = true;
-                                                       tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->transparent = Image_CheckAlpha(data, image_width * image_height, true);
+                                                       tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE);
                                                        tx->glowtexture = NULL;
                                                        qfree(data);
                                                }
index 0232c8f39e716b8d128cd9ecad9d9b68e93ebfef..db706ec77183fa82cd02c7258d8103020460a1b3 100644 (file)
@@ -47,7 +47,7 @@ extern int buildnumber;
 
 #define UNUSED(x)      (x = x) // for pesky compiler / lint warnings
 
-// LordHavoc: default heap size (unless -heapsize (win32 only) or -mem is used), in megabytes
+// LordHavoc: default heap size (unless -heapsize, -mem, or -winmem is used), in megabytes
 #define DEFAULTMEM 24
 //#define      MINIMUM_MEMORY                  0x550000
 //#define      MINIMUM_MEMORY_LEVELPAK (MINIMUM_MEMORY + 0x100000)
index c6a2b81c681ddb172aa4a4fc7de91674d64dacdd..ef7e5c648b200875f319c49551ec7057fc50bd4d 100644 (file)
@@ -121,13 +121,17 @@ void r_crosshairs_shutdown()
 {
 }
 
+void r_crosshairs_newmap()
+{
+}
+
 void R_Crosshairs_Init()
 {
        Cvar_RegisterVariable(&crosshair_brightness);
        Cvar_RegisterVariable(&crosshair_alpha);
        Cvar_RegisterVariable(&crosshair_flashspeed);
        Cvar_RegisterVariable(&crosshair_flashrange);
-       R_RegisterModule("R_Crosshairs", r_crosshairs_start, r_crosshairs_shutdown);
+       R_RegisterModule("R_Crosshairs", r_crosshairs_start, r_crosshairs_shutdown, r_crosshairs_newmap);
 }
 
 void DrawCrosshair(int num)
diff --git a/r_decals.c b/r_decals.c
new file mode 100644 (file)
index 0000000..cea29fd
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+
+#define MAX_DECALS 2048
+
+typedef struct decal_s
+{
+       vec3_t          org;
+       vec3_t          direction;
+       vec3_t          vert[4];
+       byte            color[4];
+       rtexture_t      *tex;
+       msurface_t      *surface;
+       byte            *lightmapaddress;
+       int                     lightmapstep;
+}
+decal_t;
+
+decal_t *decals;
+int currentdecal; // wraps around in decal array, replacing old ones when a new one is needed
+
+cvar_t r_drawdecals = {"r_drawdecals", "1"};
+cvar_t r_decals_lighting = {"r_decals_lighting", "1"};
+
+void r_decals_start()
+{
+       decals = (decal_t *) qmalloc(MAX_DECALS * sizeof(decal_t));
+       memset(decals, 0, MAX_DECALS * sizeof(decal_t));
+       currentdecal = 0;
+}
+
+void r_decals_shutdown()
+{
+       qfree(decals);
+}
+
+void r_decals_newmap()
+{
+       memset(decals, 0, MAX_DECALS * sizeof(decal_t));
+       currentdecal = 0;
+}
+
+void R_Decals_Init()
+{
+       Cvar_RegisterVariable (&r_drawdecals);
+       Cvar_RegisterVariable (&r_decals_lighting);
+
+       R_RegisterModule("R_Decals", r_decals_start, r_decals_shutdown, r_decals_newmap);
+}
+
+void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha)
+{
+       int i, ds, dt, bestlightmapofs;
+       float bestdist, dist;
+       vec3_t impact, right, up;
+       decal_t *decal;
+//     mleaf_t *leaf;
+       msurface_t *surf/*, **mark, **endmark*/, *bestsurf;
+
+       if (alpha < 1)
+               return;
+
+//     leaf = Mod_PointInLeaf(org, cl.worldmodel);
+//     if (!leaf->nummarksurfaces)
+//             return;
+
+//     mark = leaf->firstmarksurface;
+//     endmark = mark + leaf->nummarksurfaces;
+
+       // find the best surface to place the decal on
+       bestsurf = NULL;
+       bestdist = 16;
+       bestlightmapofs = 0;
+//     while(mark < endmark)
+//     {
+//             surf = *mark++;
+       surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
+       for (i = 0;i < cl.worldmodel->nummodelsurfaces;i++, surf++)
+       {
+               if (surf->flags & SURF_DRAWTILED)
+                       continue;       // no lightmaps
+
+               dist = PlaneDiff(org, surf->plane);
+               if (surf->flags & SURF_PLANEBACK)
+                       dist = -dist;
+               if (dist < 0)
+                       continue;
+               if (dist >= bestdist)
+                       continue;
+
+               impact[0] = org[0] - surf->plane->normal[0] * dist;
+               impact[1] = org[1] - surf->plane->normal[1] * dist;
+               impact[2] = org[2] - surf->plane->normal[2] * dist;
+
+               ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
+               dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
+
+               if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
+                       continue;
+               
+               ds -= surf->texturemins[0];
+               dt -= surf->texturemins[1];
+               
+               if (ds > surf->extents[0] || dt > surf->extents[1])
+                       continue;
+
+               bestsurf = surf;
+               bestdist = dist;
+               bestlightmapofs = (dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4);
+       }
+       // abort if no suitable surface was found
+       if (bestsurf == NULL)
+               return;
+
+       // grab a decal from the array and advance to the next decal to replace, wrapping to replace an old decal if necessary
+       decal = decals + currentdecal;
+       currentdecal++;
+       if (currentdecal >= MAX_DECALS)
+               currentdecal = 0;
+       decal->tex = tex;
+       // reverse direction
+       if (bestsurf->flags & SURF_PLANEBACK)
+       {
+               VectorCopy(bestsurf->plane->normal, decal->direction);
+       }
+       else
+       {
+               VectorNegate(bestsurf->plane->normal, decal->direction);
+       }
+       // - 0.25 to push it off the surface a bit
+       decal->org[0] = impact[0] = org[0] + decal->direction[0] * (bestdist - 0.25f);
+       decal->org[1] = impact[1] = org[1] + decal->direction[1] * (bestdist - 0.25f);
+       decal->org[2] = impact[2] = org[2] + decal->direction[2] * (bestdist - 0.25f);
+       // set up the 4 corners
+       scale *= 0.5f;
+       VectorVectors(decal->direction, right, up);
+       decal->vert[0][0] = impact[0] - up[0] * scale - right[0] * scale;
+       decal->vert[0][1] = impact[1] - up[1] * scale - right[1] * scale;
+       decal->vert[0][2] = impact[2] - up[2] * scale - right[2] * scale;
+       decal->vert[1][0] = impact[0] + up[0] * scale - right[0] * scale;
+       decal->vert[1][1] = impact[1] + up[1] * scale - right[1] * scale;
+       decal->vert[1][2] = impact[2] + up[2] * scale - right[2] * scale;
+       decal->vert[2][0] = impact[0] + up[0] * scale + right[0] * scale;
+       decal->vert[2][1] = impact[1] + up[1] * scale + right[1] * scale;
+       decal->vert[2][2] = impact[2] + up[2] * scale + right[2] * scale;
+       decal->vert[3][0] = impact[0] - up[0] * scale + right[0] * scale;
+       decal->vert[3][1] = impact[1] - up[1] * scale + right[1] * scale;
+       decal->vert[3][2] = impact[2] - up[2] * scale + right[2] * scale;
+       // store the color
+       decal->color[0] = (byte) bound(0, cred, 255);
+       decal->color[1] = (byte) bound(0, cgreen, 255);
+       decal->color[2] = (byte) bound(0, cblue, 255);
+       decal->color[3] = (byte) bound(0, alpha, 255);
+       // store the surface information for lighting
+       decal->surface = bestsurf;
+       decal->lightmapstep = ((bestsurf->extents[0]>>4)+1) * ((bestsurf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
+       if (bestsurf->samples)
+               decal->lightmapaddress = bestsurf->samples + bestlightmapofs * 3; // LordHavoc: *3 for colored lighitng
+       else
+               decal->lightmapaddress = NULL;
+}
+
+void R_DrawDecals (void)
+{
+       decal_t *p;
+       int i, j, k, dynamiclight, ir, ig, ib, maps, bits;
+       byte br, bg, bb, ba;
+       float scale, fr, fg, fb, dist, rad, mindist;
+       byte *lightmap;
+       vec3_t v;
+       msurface_t *surf;
+       dlight_t *dl;
+
+       if (!r_drawdecals.value)
+               return;
+
+       dynamiclight = (int) r_dynamic.value != 0 && (int) r_decals_lighting.value != 0;
+
+       mindist = DotProduct(r_refdef.vieworg, vpn) + 4.0f;
+
+       for (i = 0, p = decals;i < MAX_DECALS;i++, p++)
+       {
+               if (p->tex == NULL)
+                       break;
+
+               // do not render if the decal is behind the view
+               if (DotProduct(p->org, vpn) < mindist)
+                       continue;
+
+               // do not render if the view origin is behind the decal
+               VectorSubtract(p->org, r_refdef.vieworg, v);
+               if (DotProduct(p->direction, v) < 0)
+                       continue;
+
+               // get the surface lighting
+               surf = p->surface;
+               lightmap = p->lightmapaddress;
+               fr = fg = fb = 0.0f;
+               if (lightmap)
+               {
+                       for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
+                       {
+                               scale = d_lightstylevalue[surf->styles[maps]];
+                               fr += lightmap[0] * scale;
+                               fg += lightmap[1] * scale;
+                               fb += lightmap[2] * scale;
+                               lightmap += p->lightmapstep;
+                       }
+               }
+               fr *= (1.0f / 256.0f);
+               fg *= (1.0f / 256.0f);
+               fb *= (1.0f / 256.0f);
+               // dynamic lighting
+               if (dynamiclight)
+               {
+                       if (surf->dlightframe == r_dlightframecount)
+                       {
+                               for (j = 0;j < 8;j++)
+                               {
+                                       bits = surf->dlightbits[j];
+                                       if (bits)
+                                       {
+                                               for (k = 0, dl = cl_dlights + j * 32;bits;k++, dl++)
+                                               {
+                                                       if (bits & (1 << k))
+                                                       {
+                                                               bits -= 1 << k;
+                                                               VectorSubtract(p->org, dl->origin, v);
+                                                               dist = DotProduct(v, v) + LIGHTOFFSET;
+                                                               rad = dl->radius * dl->radius;
+                                                               if (dist < rad)
+                                                               {
+                                                                       rad *= 128.0f / dist;
+                                                                       fr += rad * dl->color[0];
+                                                                       fg += rad * dl->color[1];
+                                                                       fb += rad * dl->color[2];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               // apply color to lighting
+               ir = (int) (fr * p->color[0] * (1.0f / 128.0f));
+               ig = (int) (fg * p->color[1] * (1.0f / 128.0f));
+               ib = (int) (fb * p->color[2] * (1.0f / 128.0f));
+               // compute byte color
+               br = (byte) min(ir, 255);
+               bg = (byte) min(ig, 255);
+               bb = (byte) min(ib, 255);
+               ba = p->color[3];
+               // put into transpoly system for sorted drawing later
+               transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), TPOLYTYPE_ALPHA);
+               transpolyvertub(p->vert[0][0], p->vert[0][1], p->vert[0][2], 0,1,br,bg,bb,ba);
+               transpolyvertub(p->vert[1][0], p->vert[1][1], p->vert[1][2], 0,0,br,bg,bb,ba);
+               transpolyvertub(p->vert[2][0], p->vert[2][1], p->vert[2][2], 1,0,br,bg,bb,ba);
+               transpolyvertub(p->vert[3][0], p->vert[3][1], p->vert[3][2], 1,1,br,bg,bb,ba);
+               transpolyend();
+       }
+}
diff --git a/r_decals.h b/r_decals.h
new file mode 100644 (file)
index 0000000..d0aedc5
--- /dev/null
@@ -0,0 +1,6 @@
+
+void R_Decals_Init();
+
+void R_DrawDecals();
+
+void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha);
index a69d4fe2c3334798e0e6c18b057ffe5de9b18458..0350ac724b70a1b742a4ed097a5749acdf813394 100644 (file)
@@ -52,7 +52,8 @@ explosion_t explosion[128];
 rtexture_t     *explosiontexture;
 rtexture_t     *explosiontexturefog;
 
-cvar_t r_explosionclip = {"r_explosionclip", "0"};
+cvar_t r_explosionclip = {"r_explosionclip", "0", true};
+cvar_t r_drawexplosions = {"r_drawexplosions", "1"};
 
 int R_ExplosionVert(int column, int row)
 {
@@ -104,6 +105,11 @@ void r_explosion_shutdown()
 {
 }
 
+void r_explosion_newmap()
+{
+       memset(explosion, 0, sizeof(explosion));
+}
+
 void R_Explosion_Init()
 {
        int i, x, y;
@@ -133,8 +139,9 @@ void R_Explosion_Init()
        }
 
        Cvar_RegisterVariable(&r_explosionclip);
+       Cvar_RegisterVariable(&r_drawexplosions);
 
-       R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown);
+       R_RegisterModule("R_Explosions", r_explosion_start, r_explosion_shutdown, r_explosion_newmap);
 }
 
 void R_NewExplosion(vec3_t org)
@@ -255,6 +262,8 @@ void R_MoveExplosions()
 void R_DrawExplosions()
 {
        int i;
+       if (!r_drawexplosions.value)
+               return;
        for (i = 0;i < MAX_EXPLOSIONS;i++)
        {
                if (explosion[i].alpha > 0.0f)
index 39cde86d07df028f448a88452603ea3c70aadaf3..37a2a0fd1753f6ae5a0ae6ef46f375bc027c88b1 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -33,10 +33,14 @@ void r_light_shutdown()
 {
 }
 
+void r_light_newmap()
+{
+}
+
 void R_Light_Init()
 {
        Cvar_RegisterVariable(&r_lightmodels);
-       R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
+       R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap);
 }
 
 int    r_dlightframecount;
@@ -403,7 +407,7 @@ void R_PushDlights (void)
 
        for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
        {
-               if (l->die < cl.time || !l->radius)
+               if (!l->radius)
                        continue;
 //             R_MarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel->nodes );
                R_VisMarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel);
@@ -685,7 +689,7 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
                                if (!((1 << i) & dlightbits[j]))
                                        continue;
                                k = (j<<5)+i;
-                               if (cl_dlights[k].die < cl.time || !cl_dlights[k].radius)
+                               if (!cl_dlights[k].radius)
                                        continue;
                                VectorSubtract (org, cl_dlights[k].origin, dist);
                                f = DotProduct(dist, dist) + LIGHTOFFSET;
@@ -702,7 +706,7 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
        }
 }
 
-void R_CompleteLightPoint (vec3_t color, vec3_t p)
+void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic)
 {
        mleaf_t *leaf;
        leaf = Mod_PointInLeaf(p, cl.worldmodel);
@@ -721,7 +725,8 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p)
        color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
        RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
 
-       R_DynamicLightPoint(color, p, leaf->dlightbits);
+       if (dynamic)
+               R_DynamicLightPoint(color, p, leaf->dlightbits);
 }
 
 void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits)
@@ -772,7 +777,7 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
 
        for (i=0 ; i<MAX_DLIGHTS ; i++)
        {
-               if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
+               if (!cl_dlights[i].radius)
                        continue;
                VectorSubtract (org, cl_dlights[i].origin, dist);
                f = DotProduct(dist, dist) + LIGHTOFFSET;
@@ -794,7 +799,7 @@ extern float *aliasvert;
 extern float *aliasvertnorm;
 extern byte *aliasvertcolor;
 extern float modelalpha;
-void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
+void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
 {
        // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
        int i, j, nearlights = 0, color;
@@ -812,17 +817,17 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
        a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
        if (lighthalf)
        {
-               mod[0] = currententity->colormod[0] * 0.5f;
-               mod[1] = currententity->colormod[1] * 0.5f;
-               mod[2] = currententity->colormod[2] * 0.5f;
+               mod[0] = ent->colormod[0] * 0.5f;
+               mod[1] = ent->colormod[1] * 0.5f;
+               mod[2] = ent->colormod[2] * 0.5f;
        }
        else
        {
-               mod[0] = currententity->colormod[0];
-               mod[1] = currententity->colormod[1];
-               mod[2] = currententity->colormod[2];
+               mod[0] = ent->colormod[0];
+               mod[1] = ent->colormod[1];
+               mod[2] = ent->colormod[2];
        }
-       if (currententity->effects & EF_FULLBRIGHT)
+       if (ent->effects & EF_FULLBRIGHT)
        {
                ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
                ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
@@ -864,7 +869,7 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                        nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
                        nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
                        nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
-                       if (r_lightmodels.value)
+                       if (r_lightmodels.value && (ent == NULL || ent != cl_dlights[i].ent))
                                nearlights++;
                        else
                        {
index 4d7bcb551a66b9bbefddef7142f41fab750cba6b..df11b53b3c41b6c4899eaace89cdaee4d6bcdd38 100644 (file)
--- a/r_light.h
+++ b/r_light.h
@@ -7,15 +7,16 @@ typedef struct
        float   radius;
        float   die;                            // stop lighting after this time
        float   decay;                          // drop this each second
-       int             key;
+       entity_t *ent;                          // the entity that spawned this light (can be NULL if it is not to be replaced repeatedly)
        vec3_t  color;                          // LordHavoc: colored lighting
-       qboolean        dark;                   // subtracts light instead of adding
 } dlight_t;
 
 // LordHavoc: this affects the lighting scale of the whole game
 #define LIGHTOFFSET 4096.0f
 
-extern void R_CompleteLightPoint (vec3_t color, vec3_t p);
+extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic);
 extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
 extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
 extern void R_LightPoint (vec3_t color, vec3_t p);
+
+extern int r_dlightframecount;
index 1c30a4caf638fcb347205fcc74c9b9d1eed244e7..69086f6771d81d795f973b1ff9ecc3ee1b4c90eb 100644 (file)
@@ -1,46 +1,50 @@
 
 #include "quakedef.h"
 
+#define MAXRENDERMODULES 64
+
 typedef struct rendermodule_s
 {
        int active; // set by start, cleared by shutdown
        char *name;
        void(*start)();
        void(*shutdown)();
+       void(*newmap)();
 }
 rendermodule_t;
 
-rendermodule_t rendermodule[64];
+rendermodule_t rendermodule[MAXRENDERMODULES];
 
 void R_Modules_Init()
 {
        int i;
-       for (i = 0;i < 64;i++)
+       for (i = 0;i < MAXRENDERMODULES;i++)
                rendermodule[i].name = NULL;
 }
 
-void R_RegisterModule(char *name, void(*start)(), void(*shutdown)())
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)(), void(*newmap)())
 {
        int i;
-       for (i = 0;i < 64;i++)
+       for (i = 0;i < MAXRENDERMODULES;i++)
        {
                if (rendermodule[i].name == NULL)
                        break;
                if (!strcmp(name, rendermodule[i].name))
                        Sys_Error("R_RegisterModule: module \"%s\" registered twice\n", name);
        }
-       if (i >= 64)
-               Sys_Error("R_RegisterModule: ran out of renderer module slots (64)\n");
+       if (i >= MAXRENDERMODULES)
+               Sys_Error("R_RegisterModule: ran out of renderer module slots (%i)\n", MAXRENDERMODULES);
        rendermodule[i].active = 0;
        rendermodule[i].name = name;
        rendermodule[i].start = start;
        rendermodule[i].shutdown = shutdown;
+       rendermodule[i].newmap = newmap;
 }
 
-void R_StartModules ()
+void R_Modules_Start ()
 {
        int i;
-       for (i = 0;i < 64;i++)
+       for (i = 0;i < MAXRENDERMODULES;i++)
        {
                if (rendermodule[i].name == NULL)
                        continue;
@@ -51,10 +55,10 @@ void R_StartModules ()
        }
 }
 
-void R_ShutdownModules ()
+void R_Modules_Shutdown ()
 {
        int i;
-       for (i = 0;i < 64;i++)
+       for (i = 0;i < MAXRENDERMODULES;i++)
        {
                if (rendermodule[i].name == NULL)
                        continue;
@@ -65,8 +69,21 @@ void R_ShutdownModules ()
        }
 }
 
-void R_Restart ()
+void R_Modules_Restart ()
+{
+       R_Modules_Shutdown();
+       R_Modules_Start();
+}
+
+void R_Modules_NewMap ()
 {
-       R_ShutdownModules();
-       R_StartModules();
+       int i;
+       for (i = 0;i < MAXRENDERMODULES;i++)
+       {
+               if (rendermodule[i].name == NULL)
+                       continue;
+               if (!rendermodule[i].active)
+                       continue;
+               rendermodule[i].newmap();
+       }
 }
index 38aa9c627f08deeaa56d52d1a1cf94f24f0e5dec..72f41572ac4adab8eb457aa5aef970c762633748 100644 (file)
@@ -1,6 +1,7 @@
 
 void R_Modules_Init();
-void R_RegisterModule(char *name, void(*start)(), void(*shutdown)());
-void R_StartModules ();
-void R_ShutdownModules ();
-void R_Restart ();
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)(), void(*newmap)());
+void R_Modules_Start();
+void R_Modules_Shutdown();
+void R_Modules_NewMap();
+void R_Modules_Restart();
index 6abff27cd49ee2954c935faecbab0e204f7df7e8..2e3f8f361ff33c57f3584374f36115de202ac312 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // LordHavoc: added dust, smoke, snow, bloodcloud, and many others
 typedef enum
 {
-       pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_glow, pt_decal, pt_blood, pt_bloodsplatter
+       pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame/*, pt_decal*/, pt_blood, pt_oneframe, pt_lavasplash
 }
 ptype_t;
 
@@ -48,7 +48,9 @@ typedef struct particle_s
        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 of bouncing particles)
        vec3_t          oldorg;
        vec3_t          vel2; // used for snow fluttering (base velocity, wind for instance)
-       vec3_t          direction; // used by decals
+//     vec3_t          direction; // used by decals
+//     vec3_t          decalright; // used by decals
+//     vec3_t          decalup; // used by decals
 }
 particle_t;
 
@@ -62,6 +64,7 @@ rtexture_t *particletexture;
 rtexture_t *smokeparticletexture[8];
 rtexture_t *rainparticletexture;
 rtexture_t *bubbleparticletexture;
+rtexture_t *bulletholetexture[8];
 
 particle_t     *particles;
 int                    r_numparticles;
@@ -71,17 +74,22 @@ vec3_t                      r_pright, r_pup, r_ppn;
 int                    numparticles;
 particle_t     **freeparticles; // list used only in compacting particles array
 
-cvar_t r_particles = {"r_particles", "1"};
+cvar_t r_particles = {"r_particles", "1", true};
 cvar_t r_drawparticles = {"r_drawparticles", "1"};
-cvar_t r_dynamicparticles = {"r_dynamicparticles", "1", true};
+cvar_t r_particles_lighting = {"r_particles_lighting", "1", true};
+cvar_t r_particles_bloodshowers = {"r_particles_bloodshowers", "1", true};
+cvar_t r_particles_blood = {"r_particles_blood", "1", true};
+cvar_t r_particles_smoke = {"r_particles_smoke", "1", true};
+cvar_t r_particles_sparks = {"r_particles_sparks", "1", true};
+cvar_t r_particles_bubbles = {"r_particles_bubbles", "1", true};
 
 byte shadebubble(float dx, float dy, vec3_t light)
 {
        float   dz, f, dot;
        vec3_t  normal;
-       if ((dx*dx+dy*dy) < 1) // it does hit the sphere
+       dz = 1 - (dx*dx+dy*dy);
+       if (dz > 0) // it does hit the sphere
        {
-               dz = 1 - (dx*dx+dy*dy);
                f = 0;
                // back side
                normal[0] = dx;normal[1] = dy;normal[2] = dz;
@@ -122,8 +130,8 @@ void R_InitParticleTexture (void)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        dx = x - 16;
-                       d = (255 - (dx*dx+dy*dy));
-                       if (d < 0) d = 0;
+                       d = (256 - (dx*dx+dy*dy));
+                       d = bound(0, d, 255);
                        data[y][x][3] = (byte) d;
                }
        }
@@ -141,38 +149,30 @@ void R_InitParticleTexture (void)
                                dy = y - 16;
                                for (x = 0;x < 32;x++)
                                {
-                                       int j;
-                                       j = (noise1[y][x] - 128) * 2 + 128;
-                                       if (j < 0) j = 0;
-                                       if (j > 255) j = 255;
-                                       data[y][x][0] = data[y][x][1] = data[y][x][2] = j;
+                                       d = (noise1[y][x] - 128) * 2 + 128;
+                                       d = bound(0, d, 255);
+                                       data[y][x][0] = data[y][x][1] = data[y][x][2] = d;
                                        dx = x - 16;
                                        d = (noise2[y][x] - 128) * 4 + 128;
                                        if (d > 0)
-                                       {
-                                               d = (d * (255 - (int) (dx*dx+dy*dy))) >> 8;
-                                               //j = (sqrt(dx*dx+dy*dy) * 2.0f - 16.0f);
-                                               //if (j > 0)
-                                               //      d = (d * (255 - j*j)) >> 8;
-                                               if (d < 0) d = 0;
-                                               if (d > 255) d = 255;
-                                               data[y][x][3] = (byte) d;
-                                               if (m < d)
-                                                       m = d;
-                                       }
+                                               d = (d * (256 - (int) (dx*dx+dy*dy))) >> 8;
+                                       d = bound(0, d, 255);
+                                       data[y][x][3] = (byte) d;
+                                       if (m < d)
+                                               m = d;
                                }
                        }
                }
-               while (m < 192);
+               while (m < 224);
 
                smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        }
 
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
-       for (x=0 ; x<32 ; x++)
+       for (y = 0;y < 32;y++)
        {
-               for (y=0 ; y<32 ; y++)
+               for (x = 0;x < 32;x++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light);
@@ -182,15 +182,69 @@ void R_InitParticleTexture (void)
 
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
-       for (x=0 ; x<32 ; x++)
+       for (y = 0;y < 32;y++)
        {
-               for (y=0 ; y<32 ; y++)
+               for (x = 0;x < 32;x++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
                }
        }
        bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+
+       for (i = 0;i < 8;i++)
+       {
+               float p[32][32];
+               fractalnoise(&noise1[0][0], 64, 8);
+               for (y = 0;y < 32;y++)
+                       for (x = 0;x < 32;x++)
+                               p[y][x] = (noise1[y][x] / 8.0f) - 64.0f;
+               for (m = 0;m < 32;m++)
+               {
+                       int j;
+                       float fx, fy, f;
+                       fx = lhrandom(14, 18);
+                       fy = lhrandom(14, 18);
+                       do
+                       {
+                               dx = lhrandom(-1, 1);
+                               dy = lhrandom(-1, 1);
+                               f = (dx * dx + dy * dy);
+                       }
+                       while(f < 0.125f || f > 1.0f);
+                       f = (m + 1) / 40.0f; //lhrandom(0.0f, 1.0);
+                       dx *= 1.0f / 32.0f;
+                       dy *= 1.0f / 32.0f;
+                       for (j = 0;f > 0 && j < (32 * 14);j++)
+                       {
+                               y = fy;
+                               x = fx;
+                               fx += dx;
+                               fy += dy;
+                               p[y - 1][x - 1] += f * 0.125f;
+                               p[y - 1][x    ] += f * 0.25f;
+                               p[y - 1][x + 1] += f * 0.125f;
+                               p[y    ][x - 1] += f * 0.25f;
+                               p[y    ][x    ] += f;
+                               p[y    ][x + 1] += f * 0.25f;
+                               p[y + 1][x - 1] += f * 0.125f;
+                               p[y + 1][x    ] += f * 0.25f;
+                               p[y + 1][x + 1] += f * 0.125f;
+//                             f -= (0.5f / (32 * 16));
+                       }
+               }
+               for (y = 0;y < 32;y++)
+               {
+                       for (x = 0;x < 32;x++)
+                       {
+                               m = p[y][x];
+                               data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
+                               data[y][x][3] = (byte) bound(0, m, 255);
+                       }
+               }
+
+               bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       }
 }
 
 void r_part_start()
@@ -208,6 +262,11 @@ void r_part_shutdown()
        qfree(freeparticles);
 }
 
+void r_part_newmap()
+{
+       numparticles = 0;
+}
+
 /*
 ===============
 R_InitParticles
@@ -235,9 +294,14 @@ void R_Particles_Init (void)
 
        Cvar_RegisterVariable (&r_particles);
        Cvar_RegisterVariable (&r_drawparticles);
-       Cvar_RegisterVariable (&r_dynamicparticles);
-
-       R_RegisterModule("R_Particles", r_part_start, r_part_shutdown);
+       Cvar_RegisterVariable (&r_particles_lighting);
+       Cvar_RegisterVariable (&r_particles_bloodshowers);
+       Cvar_RegisterVariable (&r_particles_blood);
+       Cvar_RegisterVariable (&r_particles_smoke);
+       Cvar_RegisterVariable (&r_particles_sparks);
+       Cvar_RegisterVariable (&r_particles_bubbles);
+
+       R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
 }
 
 //void particle(int ptype, int pcolor, int ptex, int prendermode, int plight, float pscale, float palpha, float ptime, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz)
@@ -265,6 +329,7 @@ void R_Particles_Init (void)
        part->time2 = 0;\
        part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
 }
+/*
 #define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\
 {\
        particle_t      *part;\
@@ -289,6 +354,8 @@ void R_Particles_Init (void)
        part->time2 = 0;\
        part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
 }
+*/
+/*
 #define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
 {\
        particle_t      *part;\
@@ -313,6 +380,7 @@ void R_Particles_Init (void)
        part->time2 = 0;\
        part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
 }
+*/
 #define particle4(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2)\
 {\
        particle_t      *part;\
@@ -376,30 +444,11 @@ void R_EntityParticles (entity_t *ent)
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               particle(pt_static, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 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);
+               particle(pt_oneframe, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 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);
        }
 }
 
 
-/*
-===============
-R_ClearParticles
-===============
-*/
-void R_ClearParticles (void)
-{
-//     int             i;
-//     free_particles = &particles[0];
-//     active_particles = NULL;
-
-//     for (i=0 ;i<r_numparticles ; i++)
-//             particles[i].next = &particles[i+1];
-//     particles[r_numparticles-1].next = NULL;
-
-       numparticles = 0;
-}
-
-
 void R_ReadPointFile_f (void)
 {
        FILE    *f;
@@ -481,8 +530,8 @@ void R_ParticleExplosion (vec3_t org, int smoke)
        i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
        if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
        {
-               for (i=0 ; i<128 ; i++)
-                       particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 2, 1.5, org, 16, 96);
+               for (i = 0;i < 128;i++)
+                       particle(pt_bubble, 254, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96));
        }
        else
                R_NewExplosion(org);
@@ -493,9 +542,9 @@ void R_ParticleExplosion (vec3_t org, int smoke)
 //             int color;
                float f, forg[3], fvel[3], fvel2[3];
 //             for (i = 0;i < 256;i++)
-//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192);
+//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(0, 384));
 //             for (i = 0;i < 256;i++)
-//                     particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org, 15, 150);
+//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-150, 150), lhrandom(-150, 150), lhrandom(-150, 150));
                for (i = 0;i < 32;i++)
                {
                        fvel[0] = lhrandom(-150, 150);
@@ -518,11 +567,11 @@ void R_ParticleExplosion (vec3_t org, int smoke)
                        }
                }
 //             for (i = 0;i < 16;i++)
-//                     particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org, 20, 0);
+//                     particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org[0] + lhrandom(-20, 20), org[1] + lhrandom(-20, 20), org[2] + lhrandom(-20, 20), 0, 0, 0);
 //             for (i = 0;i < 50;i++)
-//                     particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org, 10, 200);
+//                     particle(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-200, 200), lhrandom(-200, 200), lhrandom(-200, 200));
 //             for (i = 0;i < 30;i++)
-//                     particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org, 10, 100);
+//                     particle(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-100, 100), lhrandom(-100, 100), lhrandom(-100, 100));
        }
        */
 }
@@ -539,7 +588,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i = 0;i < 512;i++)
-               particle2(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org, 8, 192);
+               particle(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192));
 }
 
 /*
@@ -553,10 +602,10 @@ void R_BlobExplosion (vec3_t org)
        int                     i;
        if (!r_particles.value) return; // LordHavoc: particles are optional
        
-       for (i=0 ; i<512 ; i++)
-               particle3(pt_blob, 66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128);
-       for (i=0 ; i<512 ; i++)
-               particle3(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128);
+       for (i = 0;i < 256;i++)
+               particle(pt_blob,   66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
+       for (i = 0;i < 256;i++)
+               particle(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
 }
 
 /*
@@ -575,7 +624,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                return;
        }
        while (count--)
-               particle2(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 1, 0, org, 8, 15);
+               particle(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15));
 }
 
 // LordHavoc: added this for spawning sparks/dust (which have strong gravity)
@@ -588,23 +637,34 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count)
 {
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
+       R_Decal(org, bulletholetexture[rand()&7], 16, 0, 0, 0, 255);
+
        // smoke puff
-       particle(pt_bulletsmoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 1, 160, 99, 0, org[0], org[1], org[2], lhrandom(-4, 4), lhrandom(-4, 4), 16);
-       // sparks
-       while(count--)
-               particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 1.5, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 128);
+       if (r_particles_smoke.value)
+               particle(pt_bulletsmoke, 10, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16));
+
+       if (r_particles_sparks.value)
+       {
+               // sparks
+               while(count--)
+                       particle(pt_spark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128));
+       }
 }
 
 void R_BloodPuff (vec3_t org, vec3_t vel, int count)
 {
+       // bloodcount is used to accumulate counts too small to cause a blood particle
+       static int bloodcount = 0;
        if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles_blood.value) return;
 
        if (count > 100)
                count = 100;
-       while(count > 0)
+       bloodcount += count;
+       while(bloodcount >= 10)
        {
-               particle(pt_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 20), min(count, 10) * 25 + 5, 99, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
-               count -= 10;
+               particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+               bloodcount -= 10;
        }
 }
 
@@ -614,6 +674,8 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        vec3_t          center;
        vec3_t          velscale;
        if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles_bloodshowers.value) return;
+       if (!r_particles_blood.value) return;
 
        VectorSubtract(maxs, mins, diff);
        center[0] = (mins[0] + maxs[0]) * 0.5;
@@ -633,7 +695,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
                vel[0] = (org[0] - center[0]) * velscale[0];
                vel[1] = (org[1] - center[1]) * velscale[1];
                vel[2] = (org[2] - center[2]) * velscale[2];
-               particle(pt_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 25), 255, 99, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]);
+               particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]);
        }
 }
 
@@ -704,7 +766,7 @@ void R_FlameCube (vec3_t mins, vec3_t maxs, int count)
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
        while (count--)
-               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 1, lhrandom(64, 255), 5, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 48));
+               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64));
 }
 
 void R_Flames (vec3_t org, vec3_t vel, int count)
@@ -712,7 +774,7 @@ void R_Flames (vec3_t org, vec3_t vel, int count)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        while (count--)
-               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 1, lhrandom(64, 255), 5, 1.5, org[0], org[1], org[2], vel[0] + lhrandom(-16, 16), vel[1] + lhrandom(-16, 16), vel[2] + lhrandom(-16, 16));
+               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128));
 }
 
 
@@ -730,9 +792,9 @@ void R_LavaSplash (vec3_t origin)
        vec3_t          dir, org;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       for (i=-128 ; i<128 ; i+=8)
+       for (i=-128 ; i<128 ; i+=16)
        {
-               for (j=-128 ; j<128 ; j+=8)
+               for (j=-128 ; j<128 ; j+=16)
                {
                        dir[0] = j + lhrandom(0, 8);
                        dir[1] = i + lhrandom(0, 8);
@@ -741,8 +803,8 @@ void R_LavaSplash (vec3_t origin)
                        org[1] = origin[1] + dir[1];
                        org[2] = origin[2] + lhrandom(0, 64);
                        vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
-                       particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel);
-//                     particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 0, origin[0] + i, origin[1] + j, origin[2] + lhrandom(0, 63), i * lhrandom(0.125, 0.25), j * lhrandom(0.125, 0.25), lhrandom(64, 128));
+                       particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel);
+//                     particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, origin[0] + i, origin[1] + j, origin[2] + lhrandom(0, 63), i * lhrandom(0.125, 0.25), j * lhrandom(0.125, 0.25), lhrandom(64, 128));
                }
        }
 }
@@ -761,7 +823,7 @@ void R_TeleportSplash (vec3_t org)
        for (i=-16 ; i<16 ; i+=8)
                for (j=-16 ; j<16 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
-                               particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 5, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5));
+                               particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5));
 }
 
 void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
@@ -777,7 +839,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 
        /*
        if (type == 0) // rocket glow
-               particle(pt_glow, 254, particletexture, TPOLYTYPE_ADD, false, 10, 160, 999, 0, start[0] - 12 * dir[0], start[1] - 12 * dir[1], start[2] - 12 * dir[2], 0, 0, 0);
+               particle(pt_glow, 254, particletexture, TPOLYTYPE_ADD, false, 10, 160, 9999, 0, start[0] - 12 * dir[0], start[1] - 12 * dir[1], start[2] - 12 * dir[2], 0, 0, 0);
        */
 
        t = ent->trail_time;
@@ -822,48 +884,63 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                switch (type)
                {
                        case 0: // rocket trail
-                               if (bubbles)
+                               if (!r_particles_smoke.value)
+                                       dec = cl.time - t;
+                               else if (bubbles && r_particles_bubbles.value)
                                {
                                        dec = 0.01f;
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                                }
                                else
                                {
                                        dec = 0.01f;
-                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16);
-                                       if (type == 0)
-                                       {
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-//                                             particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-//                                             particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-                                       }
+                                       particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
+//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
+//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
+//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
                                }
                                break;
 
                        case 1: // grenade trail
                                // FIXME: make it gradually stop smoking
-                               if (bubbles)
+                               if (!r_particles_smoke.value)
+                                       dec = cl.time - t;
+                               else if (bubbles && r_particles_bubbles.value)
                                {
                                        dec = 0.02f;
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                                }
                                else
                                {
                                        dec = 0.02f;
-                                       particle(pt_smoke, 6, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16);
+                                       particle(pt_smoke, 8, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                                }
                                break;
 
 
                        case 2: // blood
-                               dec = 0.025f;
-                               particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                               if (!r_particles_blood.value)
+                                       dec = cl.time - t;
+                               else
+                               {
+                                       dec = 0.2f;
+                                       particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                               }
                                break;
 
                        case 4: // slight blood
-                               dec = 0.025f;
-                               particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 192, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                               if (!r_particles_blood.value)
+                                       dec = cl.time - t;
+                               else
+                               {
+                                       dec = 0.3f;
+                                       particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                               }
                                break;
 
                        case 3: // green tracer
@@ -882,11 +959,16 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                break;
 
                        case 7: // Nehahra smoke tracer
-                               dec = 0.14f;
-                               particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                               if (!r_particles_smoke.value)
+                                       dec = cl.time - t;
+                               else
+                               {
+                                       dec = 0.14f;
+                                       particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                               }
                                break;
                }
-               
+
                // advance to next time and position
                t += dec;
                dec *= speed;
@@ -900,13 +982,14 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        vec3_t          vec;
        int                     len;
        if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles_smoke.value) return;
 
        VectorSubtract (end, start, vec);
        len = (int) (VectorNormalizeLength (vec) * (1.0f / 3.0f));
        VectorScale(vec, 3, vec);
        while (len--)
        {
-               particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 99, 0, start[0], start[1], start[2], 0, 0, 0);
+               particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                VectorAdd (start, vec, start);
        }
 }
@@ -931,6 +1014,8 @@ void R_MoveParticles (void)
                return;
 
        frametime = cl.time - cl.oldtime;
+       if (!frametime)
+               return; // if absolutely still, don't update particles
        gravity = frametime * sv_gravity.value;
        dvel = 1+4*frametime;
 
@@ -958,23 +1043,28 @@ void R_MoveParticles (void)
                                VectorCopy(v, p->org);
                                if (p->bounce < 0)
                                {
+                                       byte *color24 = (byte *) &d_8to24table[(int)p->color];
+                                       R_Decal(v, p->tex, p->scale, color24[0], color24[1], color24[2], p->alpha);
+                                       p->die = -1;
+                                       freeparticles[j++] = p;
+                                       continue;
+                                       /*
                                        VectorClear(p->vel);
                                        p->type = pt_decal;
                                        // have to negate the direction (why?)
                                        VectorNegate(normal, p->direction);
+                                       VectorVectors(p->direction, p->decalright, p->decalup);
+                                       VectorSubtract(p->org, p->direction, p->org); // push off the surface a bit so it doesn't flicker
                                        p->bounce = 0;
                                        p->time2 = cl.time + 30;
+                                       */
                                }
                                else
                                {
                                        dist = DotProduct(p->vel, normal) * -p->bounce;
                                        VectorMAQuick(p->vel, dist, normal, p->vel);
                                        if (DotProduct(p->vel, p->vel) < 0.03)
-                                       {
                                                VectorClear(p->vel);
-                                               // hack - world is static, therefore there won't be any moving or disappearing surfaces to worry about
-                                               //p->bounce = 0;
-                                       }
                                }
                        }
                }
@@ -990,6 +1080,9 @@ void R_MoveParticles (void)
                case pt_blob2:
                        p->vel[0] *= dvel;
                        p->vel[1] *= dvel;
+                       p->alpha -= frametime * 256;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
 
                case pt_grav:
@@ -998,6 +1091,12 @@ void R_MoveParticles (void)
                case pt_slowgrav:
                        p->vel[2] -= gravity * 0.05;
                        break;
+               case pt_lavasplash:
+                       p->vel[2] -= gravity * 0.05;
+                       p->alpha -= frametime * 192;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
                case pt_snow:
                        if (cl.time > p->time2)
                        {
@@ -1019,7 +1118,7 @@ void R_MoveParticles (void)
                                case CONTENTS_LAVA:
                                case CONTENTS_SLIME:
                                        p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_smokecloud;
+                                       p->type = pt_steam;
                                        p->alpha = 96;
                                        p->scale = 5;
                                        p->vel[2] = 96;
@@ -1041,43 +1140,16 @@ void R_MoveParticles (void)
                                }
                        }
                        break;
-               case pt_bloodcloud:
-//                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
-//                     {
-//                             p->die = -1;
-//                             break;
-//                     }
-                       p->scale += frametime * 16;
-                       p->alpha -= frametime * 256;
-                       p->vel[2] -= gravity * 0.25;
-                       if (p->alpha < 1)
-                               p->die = -1;
-                       break;
                case pt_blood:
-//                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
-//                     {
-//                             p->die = -1;
-//                             break;
-//                     }
-                       p->scale += frametime * 16;
-                       p->alpha -= frametime * 512;
-                       p->vel[2] -= gravity * 0.25;
-                       if (p->alpha < 1)
-                               p->die = -1;
-                       break;
-               case pt_bloodsplatter:
-//                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
-//                     {
-//                             p->die = -1;
-//                             break;
-//                     }
-                       p->alpha -= frametime * 128;
-                       if (p->alpha < 1)
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                       {
                                p->die = -1;
+                               break;
+                       }
                        p->vel[2] -= gravity * 0.5;
                        break;
-               case pt_fallfadespark:
-                       p->alpha -= frametime * 256;
+               case pt_spark:
+                       p->alpha -= frametime * 512;
                        p->vel[2] -= gravity;
                        if (p->alpha < 1)
                                p->die = -1;
@@ -1092,12 +1164,10 @@ void R_MoveParticles (void)
                        if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
                        {
                                p->tex = smokeparticletexture[rand()&7];
-                               p->type = pt_splash;
-                               p->alpha = 96;
-                               p->scale = 5;
+                               p->type = pt_splashpuff;
+                               p->scale = 4;
                                p->vel[0] = p->vel[1] = p->vel[2] = 0;
-                               p->die = cl.time + 1000;
-//                             p->die = -1;
+                               break;
                        }
                        p->vel[2] += gravity * 0.25;
                        p->vel[0] *= (1 - (frametime * 0.0625));
@@ -1110,37 +1180,34 @@ void R_MoveParticles (void)
                                p->vel[1] += lhrandom(-32,32);
                                p->vel[2] += lhrandom(-32,32);
                        }
-                       p->alpha -= frametime * 64;
-                       if (p->alpha < 1)
-                               p->die = -1;
+                       p->alpha -= frametime * 256;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
-// LordHavoc: for smoke trails
                case pt_bulletsmoke:
-                       p->scale += frametime * 60;
-                       p->alpha -= frametime * 512;
+                       p->scale += frametime * 16;
+                       p->alpha -= frametime * 1024;
                        p->vel[2] += gravity * 0.05;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_smoke:
-                       p->scale += frametime * 20;
-                       p->alpha -= frametime * 256;
+                       p->scale += frametime * 32;
+                       p->alpha -= frametime * 512;
                        p->vel[2] += gravity * 0.05;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
-               case pt_smokecloud:
-                       p->scale += frametime * 64;
-                       p->alpha -= frametime * 256;
+               case pt_steam:
+                       p->scale += frametime * 48;
+                       p->alpha -= frametime * 512;
                        p->vel[2] += gravity * 0.05;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
-               case pt_splash:
-                       p->scale += frametime * 24;
-                       p->alpha -= frametime * 512;
+               case pt_splashpuff:
+//                     p->scale += frametime * 24;
+                       p->alpha -= frametime * 1024;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
@@ -1158,36 +1225,30 @@ void R_MoveParticles (void)
                                case CONTENTS_LAVA:
                                case CONTENTS_SLIME:
                                        p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_smokecloud;
-                                       p->alpha = 96;
-                                       p->scale = 5;
+                                       p->type = pt_steam;
+                                       p->scale = 3;
                                        p->vel[2] = 96;
                                        break;
                                case CONTENTS_WATER:
                                        p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_splash;
-                                       p->alpha = 96;
-                                       p->scale = 5;
+                                       p->type = pt_splashpuff;
+                                       p->scale = 4;
                                        break;
                                default: // CONTENTS_SOLID and any others
                                        TraceLine(p->oldorg, p->org, v, normal);
                                        VectorCopy(v, p->org);
                                        p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_splash;
-                                       p->alpha = 96;
-                                       p->scale = 5;
-                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1,  64, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
-                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 128, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
-                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 192, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
-                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 255, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
+                                       p->type = pt_splashpuff;
+                                       p->scale = 4;
                                        break;
                                }
                        }
                        break;
                case pt_flame:
                        p->alpha -= frametime * 512;
-                       p->vel[2] += gravity * 0.2;
-                       if (p->alpha < 1)
+                       p->vel[2] += gravity;
+//                     p->scale -= frametime * 16;
+                       if (p->alpha < 16)
                                p->die = -1;
                        break;
                        /*
@@ -1195,7 +1256,7 @@ void R_MoveParticles (void)
                        if (cl.time >= p->time2)
                        {
                                p->time2 = cl.time + 0.01;
-                               particle2(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 999, 0, p->org, 0, 50);
+                               particle(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
                        }
                        p->alpha -= frametime * 512;
                        p->vel[2] -= gravity * 0.5f;
@@ -1208,7 +1269,7 @@ void R_MoveParticles (void)
                        if (cl.time >= p->time2)
                        {
                                p->time2 = cl.time + 0.01;
-                               particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 999, 0, p->org, 0, 50);
+                               particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
                        }
                        p->alpha -= frametime * 512;
                        p->vel[2] -= gravity * 0.5f;
@@ -1224,11 +1285,7 @@ void R_MoveParticles (void)
                                p->die = -1;
                        break;
                        */
-               case pt_glow:
-                       if (p->time2)
-                               p->die = -1;
-                       p->time2 = 1;
-                       break;
+                       /*
                case pt_decal:
                        if (cl.time > p->time2)
                        {
@@ -1239,6 +1296,12 @@ void R_MoveParticles (void)
                        if (p->alpha < 64)
                                p->die = -1;
                        break;
+                       */
+               case pt_oneframe:
+                       if (p->time2)
+                               p->die = -1;
+                       p->time2 = 1;
+                       break;
                default:
                        printf("unknown particle type %i\n", p->type);
                        p->die = -1;
@@ -1268,23 +1331,21 @@ void R_MoveParticles (void)
 void R_DrawParticles (void)
 {
        particle_t              *p;
-       int                             i, r,g,b,a, dynlight;
+       int                             i, dynamiclight, staticlight, r, g, b;
+       byte                    br, bg, bb, ba;
        float                   scale, scale2, minparticledist;
        byte                    *color24;
-       vec3_t                  up, right, uprightangles, up2, right2, tempcolor, corner, decalright, decalup, v;
+       vec3_t                  uprightangles, up2, right2, tempcolor, corner;
 
        // LordHavoc: early out condition
        if ((!numparticles) || (!r_drawparticles.value))
                return;
 
-       dynlight = r_dynamicparticles.value;
+       staticlight = dynamiclight = r_particles_lighting.value;
        if (!r_dynamic.value)
-               dynlight = 0;
+               dynamiclight = 0;
        c_particles += numparticles;
 
-       VectorScale (vup, 1.5, up);
-       VectorScale (vright, 1.5, right);
-
        uprightangles[0] = 0;
        uprightangles[1] = r_refdef.viewangles[1];
        uprightangles[2] = 0;
@@ -1298,61 +1359,66 @@ void R_DrawParticles (void)
 //             if (p->die < cl.time)
 //                     continue;
 
+               // LordHavoc: only render if not too close
+               if (DotProduct(p->org, vpn) < minparticledist)
+                       continue;
+
+               /*
                if (p->type == pt_decal)
                {
                        VectorSubtract(p->org, r_refdef.vieworg, v);
                        if (DotProduct(p->direction, v) < 0)
                                continue;
                }
-
-               // LordHavoc: only render if not too close
-               if (DotProduct(p->org, vpn) < minparticledist)
-                       continue;
+               */
 
                color24 = (byte *) &d_8to24table[(int)p->color];
                r = color24[0];
                g = color24[1];
                b = color24[2];
-               a = p->alpha;
-               if (dynlight && (p->dynlight || dynlight >= 2)) // LordHavoc: only light blood and smoke
+               if (staticlight && (p->dynlight || staticlight >= 2)) // LordHavoc: only light blood and smoke
                {
-                       R_CompleteLightPoint(tempcolor, p->org);
+                       R_CompleteLightPoint(tempcolor, p->org, dynamiclight);
                        r = (r * (int) tempcolor[0]) >> 7;
                        g = (g * (int) tempcolor[1]) >> 7;
                        b = (b * (int) tempcolor[2]) >> 7;
                }
+               br = (byte) min(r, 255);
+               bg = (byte) min(g, 255);
+               bb = (byte) min(b, 255);
+               ba = (byte) p->alpha;
                transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), p->rendermode);
                scale = p->scale * -0.5;scale2 = p->scale;
+               /*
                if (p->type == pt_decal)
                {
-                       VectorVectors(p->direction, decalright, decalup);
-                       corner[0] = p->org[0] + decalup[0]*scale + decalright[0]*scale;
-                       corner[1] = p->org[1] + decalup[1]*scale + decalright[1]*scale;
-                       corner[2] = p->org[2] + decalup[2]*scale + decalright[2]*scale;
-                       transpolyvert(corner[0]                                           , corner[1]                                           , corner[2]                                           , 0,1,r,g,b,a);
-                       transpolyvert(corner[0] + decalup[0]*scale2                       , corner[1] + decalup[1]*scale2                       , corner[2] + decalup[2]*scale2                       , 0,0,r,g,b,a);
-                       transpolyvert(corner[0] + decalup[0]*scale2 + decalright[0]*scale2, corner[1] + decalup[1]*scale2 + decalright[1]*scale2, corner[2] + decalup[2]*scale2 + decalright[2]*scale2, 1,0,r,g,b,a);
-                       transpolyvert(corner[0]                     + decalright[0]*scale2, corner[1]                     + decalright[1]*scale2, corner[2]                     + decalright[2]*scale2, 1,1,r,g,b,a);
+                       corner[0] = p->org[0] + p->decalup[0]*scale + p->decalright[0]*scale;
+                       corner[1] = p->org[1] + p->decalup[1]*scale + p->decalright[1]*scale;
+                       corner[2] = p->org[2] + p->decalup[2]*scale + p->decalright[2]*scale;
+                       transpolyvertub(corner[0]                                                 , corner[1]                                                 , corner[2]                                                 , 0,1,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + p->decalup[0]*scale2                          , corner[1] + p->decalup[1]*scale2                          , corner[2] + p->decalup[2]*scale2                          , 0,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + p->decalup[0]*scale2 + p->decalright[0]*scale2, corner[1] + p->decalup[1]*scale2 + p->decalright[1]*scale2, corner[2] + p->decalup[2]*scale2 + p->decalright[2]*scale2, 1,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0]                        + p->decalright[0]*scale2, corner[1]                        + p->decalright[1]*scale2, corner[2]                        + p->decalright[2]*scale2, 1,1,br,bg,bb,ba);
                }
-               else if (p->tex == rainparticletexture) // rain streak
+               else*/ if (p->tex == rainparticletexture) // rain streak
                {
                        corner[0] = p->org[0] + up2[0]*scale + right2[0]*scale;
                        corner[1] = p->org[1] + up2[1]*scale + right2[1]*scale;
                        corner[2] = p->org[2] + up2[2]*scale + right2[2]*scale;
-                       transpolyvert(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,r,g,b,a);
-                       transpolyvert(corner[0] + up2[0]*scale2                   , corner[1] + up2[1]*scale2                   , corner[2] + up2[2]*scale2                   , 0,0,r,g,b,a);
-                       transpolyvert(corner[0] + up2[0]*scale2 + right2[0]*scale2, corner[1] + up2[1]*scale2 + right2[1]*scale2, corner[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a);
-                       transpolyvert(corner[0]                 + right2[0]*scale2, corner[1]                 + right2[1]*scale2, corner[2]                 + right2[2]*scale2, 1,1,r,g,b,a);
+                       transpolyvertub(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + up2[0]*scale2                   , corner[1] + up2[1]*scale2                   , corner[2] + up2[2]*scale2                   , 0,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + up2[0]*scale2 + right2[0]*scale2, corner[1] + up2[1]*scale2 + right2[1]*scale2, corner[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0]                 + right2[0]*scale2, corner[1]                 + right2[1]*scale2, corner[2]                 + right2[2]*scale2, 1,1,br,bg,bb,ba);
                }
                else
                {
-                       corner[0] = p->org[0] + up[0]*scale + right[0]*scale;
-                       corner[1] = p->org[1] + up[1]*scale + right[1]*scale;
-                       corner[2] = p->org[2] + up[2]*scale + right[2]*scale;
-                       transpolyvert(corner[0]                                 , corner[1]                                 , corner[2]                                 , 0,1,r,g,b,a);
-                       transpolyvert(corner[0] + up[0]*scale2                  , corner[1] + up[1]*scale2                  , corner[2] + up[2]*scale2                  , 0,0,r,g,b,a);
-                       transpolyvert(corner[0] + up[0]*scale2 + right[0]*scale2, corner[1] + up[1]*scale2 + right[1]*scale2, corner[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a);
-                       transpolyvert(corner[0]                + right[0]*scale2, corner[1]                + right[1]*scale2, corner[2]                + right[2]*scale2, 1,1,r,g,b,a);
+                       corner[0] = p->org[0] + vup[0]*scale + vright[0]*scale;
+                       corner[1] = p->org[1] + vup[1]*scale + vright[1]*scale;
+                       corner[2] = p->org[2] + vup[2]*scale + vright[2]*scale;
+                       transpolyvertub(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + vup[0]*scale2                   , corner[1] + vup[1]*scale2                   , corner[2] + vup[2]*scale2                   , 0,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0] + vup[0]*scale2 + vright[0]*scale2, corner[1] + vup[1]*scale2 + vright[1]*scale2, corner[2] + vup[2]*scale2 + vright[2]*scale2, 1,0,br,bg,bb,ba);
+                       transpolyvertub(corner[0]                 + vright[0]*scale2, corner[1]                 + vright[1]*scale2, corner[2]                 + vright[2]*scale2, 1,1,br,bg,bb,ba);
                }
                transpolyend();
        }
index 13db9a0071681ea0791fcdd5e62535587159f699..db8e90e934c588cec1ac93d852b5a2d72c9c1330 100644 (file)
@@ -56,7 +56,7 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
                color[2] = e->colormod[2] * 255;
        }
        else
-               R_CompleteLightPoint(color, e->origin);
+               R_CompleteLightPoint(color, e->origin, true);
 
        colorub[0] = bound(0, color[0], 255);
        colorub[1] = bound(0, color[1], 255);
index 5cf362e6547b4f2e65c306d45f8677407700a982..e69a5bddd018333184df7afa8516fa458c466ba5 100644 (file)
--- a/render.h
+++ b/render.h
@@ -147,6 +147,7 @@ void R_RemoveEfrags (entity_t *ent);
 
 void R_NewMap (void);
 
+#include "r_decals.h"
 
 void R_ParseParticleEffect (void);
 void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
index 1a725ebbabf36f4852b7510beb153cf82e2760bd..1fb72b99808199d83b3657f02cc0b20befc99df4 100644 (file)
--- a/snd_win.c
+++ b/snd_win.c
@@ -207,11 +207,9 @@ sndinitstat SNDDMA_InitDirect (void)
     format.nChannels = shm->channels;
     format.wBitsPerSample = shm->samplebits;
     format.nSamplesPerSec = shm->speed;
-    format.nBlockAlign = format.nChannels
-               *format.wBitsPerSample / 8;
+    format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
     format.cbSize = 0;
-    format.nAvgBytesPerSec = format.nSamplesPerSec
-               *format.nBlockAlign; 
+    format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; 
 
        if (!hInstDS)
        {
index da6ae1d7f5748b2d8de8d78e86f11ec50b5e45a0..cc2ef249b8f95646fd3e05f4e596d4ca09209fe4 100644 (file)
@@ -399,7 +399,6 @@ int main (int c, char **v)
        double          time, oldtime, newtime;
        extern int vcrFile;
        extern int recording;
-       int j;
 
 //     static char cwd[1024];
 
@@ -414,16 +413,6 @@ int main (int c, char **v)
 
        host_parms.memsize = DEFAULTMEM * 1024*1024;
 
-       j = COM_CheckParm("-mem");
-       if (j)
-               host_parms.memsize = (int) (atof(com_argv[j+1]) * 1024 * 1024);
-       host_parms.membase = qmalloc(host_parms.memsize);
-       if (!host_parms.membase)
-       {
-               printf("Unable to allocate heap memory\n");
-               return 1;
-       }
-
        host_parms.basedir = basedir;
 // caching is disabled by default, use -cachedir to enable
 //     host_parms.cachedir = cachedir;
index 90b04ed8ab97999fd7af88d72aeb48c55e3e9f6b..8452c9ae2f92acdde19a63645dfa965c8e81554c 100644 (file)
--- a/sys_win.c
+++ b/sys_win.c
@@ -695,25 +695,6 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
        if (host_parms.memsize > MAXIMUM_WIN_MEMORY)
                host_parms.memsize = MAXIMUM_WIN_MEMORY;
        */
-       host_parms.memsize = DEFAULTMEM * 1048576;
-
-       if ((t = COM_CheckParm("-heapsize")))
-       {
-               t++;
-               if (t < com_argc)
-                       host_parms.memsize = atoi (com_argv[t]) * 1024;
-       }
-       else if ((t = COM_CheckParm("-mem")) || (t = COM_CheckParm("-winmem")))
-       {
-               t++;
-               if (t < com_argc)
-                       host_parms.memsize = atoi (com_argv[t]) * 1048576;
-       }
-
-       host_parms.membase = qmalloc(host_parms.memsize);
-
-       if (!host_parms.membase)
-               Sys_Error ("Not enough memory free; check disk space\n");
 
 //     Sys_PageIn (parms.membase, parms.memsize);