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 61630a2..01bea5c 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 7a6623a..40b42eb 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 368bf3d..d856ce1 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 1046cbc..363ca59 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 9abe25e..f7aa2af 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 93622b1..3425daf 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 f2c9465..5a348d3 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 99e7114..6065452 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 4eb8baf..d2114ab 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 24ece5f..25747e9 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 c4a257d..f3806a3 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 c5c367d..72dc5e4 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 026861d..b19aa68 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 a5644a3..6248f5b 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 3d687b6..7c165ad 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 7b05a23..a26b78f 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 60a9759..9fc65f0 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 ea8fb19..7cbbad7 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 3335040..8604c43 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 0232c8f..db706ec 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 c6a2b81..ef7e5c6 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 a69d4fe..0350ac7 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 39cde86..37a2a0f 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 4d7bcb5..df11b53 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 1c30a4c..69086f6 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 38aa9c6..72f4157 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 6abff27..2e3f8f3 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 13db9a0..db8e90e 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 5cf362e..e69a5bd 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 1a725eb..1fb72b9 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 da6ae1d..cc2ef24 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 90b04ed..8452c9a 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);