replaced cl_beams_relative cvar with cl_beams_quakepositionhack and cl_beams_instanta...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 25 May 2006 04:12:05 +0000 (04:12 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 25 May 2006 04:12:05 +0000 (04:12 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6380 d7cf8633-e32d-0410-b094-e92efae38249

cl_main.c
cl_parse.c
client.h
clvm_cmds.c
menu.c
r_lightning.c
todo

index 05570d7..d205895 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -64,8 +64,9 @@ cvar_t cl_stainmaps = {CVAR_SAVE, "cl_stainmaps", "1","stains lightmaps, much fa
 cvar_t cl_stainmaps_clearonload = {CVAR_SAVE, "cl_stainmaps_clearonload", "1","clear stainmaps on map restart"};
 
 cvar_t cl_beams_polygons = {CVAR_SAVE, "cl_beams_polygons", "1","use beam polygons instead of models"};
-cvar_t cl_beams_relative = {CVAR_SAVE, "cl_beams_relative", "1","beams are relative to owner (smooth sweeps)"};
-cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0","make a light at the end of the beam"};
+cvar_t cl_beams_quakepositionhack = {CVAR_SAVE, "cl_beams_quakepositionhack", "1", "makes your lightning gun appear to fire from your waist (as in Quake and QuakeWorld)"};
+cvar_t cl_beams_instantaimhack = {CVAR_SAVE, "cl_beams_instantaimhack", "1", "makes your lightning gun aiming update instantly"};
+cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0", "make a light at the end of the beam"};
 
 cvar_t cl_noplayershadow = {CVAR_SAVE, "cl_noplayershadow", "0","hide player shadow"};
 
@@ -1381,11 +1382,44 @@ static void CL_RelinkEffects(void)
        }
 }
 
+void CL_Beam_CalculatePositions(const beam_t *b, vec3_t start, vec3_t end)
+{
+       VectorCopy(b->start, start);
+       VectorCopy(b->end, end);
+
+       // if coming from the player, update the start position
+       if (b->entity == cl.viewentity)
+       {
+               if (cl_beams_quakepositionhack.integer && !chase_active.integer)
+               {
+                       // LordHavoc: this is a stupid hack from Quake that makes your
+                       // lightning appear to come from your waist and cover less of your
+                       // view
+                       // in Quake this hack was applied to all players (causing the
+                       // infamous crotch-lightning), but in darkplaces and QuakeWorld it
+                       // only applies to your own lightning, and only in first person
+                       Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, start);
+               }
+               if (cl_beams_instantaimhack.integer)
+               {
+                       vec3_t dir, localend;
+                       vec_t len;
+                       // LordHavoc: this updates the beam direction to match your
+                       // viewangles
+                       VectorSubtract(end, start, dir);
+                       len = VectorLength(dir);
+                       VectorNormalize(dir);
+                       VectorSet(localend, len, 0, 0);
+                       Matrix4x4_Transform(&r_view.matrix, localend, end);
+               }
+       }
+}
+
 void CL_RelinkBeams(void)
 {
        int i;
        beam_t *b;
-       vec3_t dist, org;
+       vec3_t dist, org, start, end;
        float d;
        entity_t *ent;
        float yaw, pitch;
@@ -1402,24 +1436,14 @@ void CL_RelinkBeams(void)
                        continue;
                }
 
-               // if coming from the player, update the start position
-               //if (b->entity == cl.viewentity)
-               //      Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, b->start);
-               if (cl_beams_relative.integer >= 1 && b->entity && (b->entity == cl.viewentity || cl_beams_relative.integer >= 2) && cl.entities[b->entity].state_current.active && b->relativestartvalid)
-               {
-                       entity_render_t *r = &cl.entities[b->entity].render;
-                       //Matrix4x4_OriginFromMatrix(&r->matrix, origin);
-                       //Matrix4x4_CreateFromQuakeEntity(&matrix, r->origin[0], r->origin[1], r->origin[2] + 16, r->angles[0], r->angles[1], r->angles[2], 1);
-                       Matrix4x4_Transform(&r->matrix, b->relativestart, b->start);
-                       Matrix4x4_Transform(&r->matrix, b->relativeend, b->end);
-               }
+               CL_Beam_CalculatePositions(b, start, end);
 
                if (b->lightning)
                {
                        if (cl_beams_lightatend.integer)
                        {
                                // FIXME: create a matrix from the beam start/end orientation
-                               Matrix4x4_CreateTranslate(&tempmatrix, b->end[0], b->end[1], b->end[2]);
+                               Matrix4x4_CreateTranslate(&tempmatrix, end[0], end[1], end[2]);
                                CL_AllocDlight (NULL, &tempmatrix, 200, 0.3, 0.7, 1, 0, 0, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
                        }
                        if (cl_beams_polygons.integer)
@@ -1427,8 +1451,8 @@ void CL_RelinkBeams(void)
                }
 
                // calculate pitch and yaw
-               VectorSubtract (b->end, b->start, dist);
-
+               // (this is similar to the QuakeC builtin function vectoangles)
+               VectorSubtract(end, start, dist);
                if (dist[1] == 0 && dist[0] == 0)
                {
                        yaw = 0;
@@ -1450,7 +1474,7 @@ void CL_RelinkBeams(void)
                }
 
                // add new entities for the lightning
-               VectorCopy (b->start, org);
+               VectorCopy (start, org);
                d = VectorNormalizeLength(dist);
                while (d > 0)
                {
@@ -1742,7 +1766,8 @@ void CL_Init (void)
        Cvar_RegisterVariable(&cl_stainmaps);
        Cvar_RegisterVariable(&cl_stainmaps_clearonload);
        Cvar_RegisterVariable(&cl_beams_polygons);
-       Cvar_RegisterVariable(&cl_beams_relative);
+       Cvar_RegisterVariable(&cl_beams_quakepositionhack);
+       Cvar_RegisterVariable(&cl_beams_instantaimhack);
        Cvar_RegisterVariable(&cl_beams_lightatend);
        Cvar_RegisterVariable(&cl_noplayershadow);
 
index c62bfe9..ae542ba 100644 (file)
@@ -1501,19 +1501,14 @@ void CL_ParseEffect2 (void)
        CL_Effect(org, modelindex, startframe, framecount, framerate);
 }
 
-void CL_ParseBeam (model_t *m, int lightning)
+void CL_NewBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
 {
-       int i, ent;
-       vec3_t start, end;
+       int i;
        beam_t *b = NULL;
 
-       ent = (unsigned short) MSG_ReadShort ();
-       MSG_ReadVector(start, cls.protocol);
-       MSG_ReadVector(end, cls.protocol);
-
        if (ent >= MAX_EDICTS)
        {
-               Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
+               Con_Printf("CL_NewBeam: invalid entity number %i\n", ent);
                ent = 0;
        }
 
@@ -1529,7 +1524,7 @@ void CL_ParseBeam (model_t *m, int lightning)
        // if the entity was not found then just replace an unused beam
        if (i == cl.max_beams)
                for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-                       if (!b->model || b->endtime < cl.time)
+                       if (!b->model)
                                break;
        if (i < cl.max_beams)
        {
@@ -1537,36 +1532,32 @@ void CL_ParseBeam (model_t *m, int lightning)
                b->entity = ent;
                b->lightning = lightning;
                b->model = m;
-               b->endtime = cl.time + 0.2;
+               b->endtime = cl.mtime[0] + 0.2;
                VectorCopy (start, b->start);
                VectorCopy (end, b->end);
-               b->relativestartvalid = 0;
-               if (ent && cl.entities[ent].state_current.active)
-               {
-                       entity_state_t *p;
-                       matrix4x4_t matrix, imatrix;
-                       if (ent == cl.viewentity && cl.movement)
-                               p = &cl.entities[b->entity].state_previous;
-                       else
-                               p = &cl.entities[b->entity].state_current;
-                       // not really valid yet, we need to get the orientation now
-                       // (ParseBeam flagged this because it is received before
-                       //  entities are received, by now they have been received)
-                       // note: because players create lightning in their think
-                       // function (which occurs before movement), they actually
-                       // have some lag in it's location, so compare to the
-                       // previous player state, not the latest
-                       Matrix4x4_CreateFromQuakeEntity(&matrix, p->origin[0], p->origin[1], p->origin[2], -p->angles[0], p->angles[1], p->angles[2], 1);
-                       Matrix4x4_Invert_Simple(&imatrix, &matrix);
-                       Matrix4x4_Transform(&imatrix, b->start, b->relativestart);
-                       Matrix4x4_Transform(&imatrix, b->end, b->relativeend);
-                       b->relativestartvalid = 1;
-               }
        }
        else
                Con_Print("beam list overflow!\n");
 }
 
+void CL_ParseBeam (model_t *m, int lightning)
+{
+       int ent;
+       vec3_t start, end;
+
+       ent = (unsigned short) MSG_ReadShort ();
+       MSG_ReadVector(start, cls.protocol);
+       MSG_ReadVector(end, cls.protocol);
+
+       if (ent >= MAX_EDICTS)
+       {
+               Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
+               ent = 0;
+       }
+
+       CL_NewBeam(ent, start, end, m, lightning);
+}
+
 void CL_ParseTempEntity(void)
 {
        int type;
index f9b16e3..cfa3f3d 100644 (file)
--- a/client.h
+++ b/client.h
@@ -55,12 +55,6 @@ typedef struct beam_s
        struct model_s  *model;
        float   endtime;
        vec3_t  start, end;
-       // if this beam is owned by an entity, this is the beam start relative to
-       // that entity's matrix for per frame start updates
-       vec3_t  relativestart;
-       vec3_t  relativeend;
-       // indicates whether relativestart is valid
-       int     relativestartvalid;
 }
 beam_t;
 
@@ -963,10 +957,6 @@ void CL_Disconnect_f (void);
 
 void CL_BoundingBoxForEntity(entity_render_t *ent);
 
-extern cvar_t cl_beams_polygons;
-extern cvar_t cl_beams_relative;
-extern cvar_t cl_beams_lightatend;
-
 //
 // cl_input
 //
@@ -988,7 +978,9 @@ void CL_ValidateState(entity_state_t *s);
 void CL_MoveLerpEntityStates(entity_t *ent);
 void CL_LerpUpdate(entity_t *e);
 void CL_ParseTEnt (void);
+void CL_NewBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning);
 void CL_RelinkBeams (void);
+void CL_Beam_CalculatePositions (const beam_t *b, vec3_t start, vec3_t end);
 
 void CL_ClearTempEntities (void);
 entity_t *CL_NewTempEntity (void);
index 011de9b..a1a7d6e 100644 (file)
@@ -1032,45 +1032,6 @@ void VM_CL_particleeffectnum (void)
        PRVM_G_FLOAT(OFS_RETURN) = i;
 }
 
-void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning)
-{
-       int             i;
-       beam_t  *b;
-
-       // override any beam with the same entity
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
-}
-
 // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
 void VM_CL_trailparticles (void)
 {
@@ -1656,74 +1617,32 @@ void VM_CL_te_explosion2 (void)
 }
 
 
-static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning)
-{
-       beam_t  *b;
-       int             i;
-
-       if (ent >= cl.max_csqcentities)
-               CL_ExpandCSQCEntities(ent);
-
-       // override any beam with the same entity
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (b->entity == ent && ent)
-               {
-                       //b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-
-       // find a free beam
-       for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++)
-       {
-               if (!b->model || b->endtime < cl.time)
-               {
-                       b->entity = ent;
-                       b->lightning = lightning;
-                       b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0;
-                       b->model = m;
-                       b->endtime = cl.time + 0.2;
-                       VectorCopy (start, b->start);
-                       VectorCopy (end, b->end);
-                       return;
-               }
-       }
-       Con_Print("beam list overflow!\n");
-}
-
 // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning1 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
 }
 
 // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning2 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
 }
 
 // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_lightning3 (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
 }
 
 // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
 void VM_CL_te_beam (void)
 {
        VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
-       VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
+       CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
 }
 
 // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
diff --git a/menu.c b/menu.c
index 25e2ab5..226b299 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -1794,7 +1794,7 @@ static void M_Options_Key (int k, char ascii)
        }
 }
 
-#define        OPTIONS_EFFECTS_ITEMS   35
+#define        OPTIONS_EFFECTS_ITEMS   36
 
 static int options_effects_cursor;
 
@@ -1811,8 +1811,9 @@ extern cvar_t cl_stainmaps_clearonload;
 extern cvar_t r_explosionclip;
 extern cvar_t r_coronas;
 extern cvar_t gl_flashblend;
-extern cvar_t cl_beams_polygon;
-extern cvar_t cl_beams_relative;
+extern cvar_t cl_beams_polygons;
+extern cvar_t cl_beams_quakepositionhack;
+extern cvar_t cl_beams_instantaimhack;
 extern cvar_t cl_beams_lightatend;
 extern cvar_t r_lightningbeam_thickness;
 extern cvar_t r_lightningbeam_scroll;
@@ -1846,7 +1847,8 @@ static void M_Menu_Options_Effects_AdjustSliders (int dir)
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_particles_blood_alpha, bound(0.2, cl_particles_blood_alpha.value + dir * 0.1, 1));
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_particles_blood_bloodhack, !cl_particles_blood_bloodhack.integer);
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_polygons, !cl_beams_polygons.integer);
-       else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_relative, !cl_beams_relative.integer);
+       else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_instantaimhack, !cl_beams_instantaimhack.integer);
+       else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_quakepositionhack, !cl_beams_quakepositionhack.integer);
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_lightatend, !cl_beams_lightatend.integer);
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&r_lightningbeam_thickness, bound(1, r_lightningbeam_thickness.integer + dir, 10));
        else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&r_lightningbeam_scroll, bound(0, r_lightningbeam_scroll.integer + dir, 10));
@@ -1898,8 +1900,9 @@ static void M_Options_Effects_Draw (void)
        M_Options_PrintCheckbox("                 Blood", true, cl_particles_blood.integer);
        M_Options_PrintSlider(  "         Blood Opacity", true, cl_particles_blood_alpha.value, 0.2, 1);
        M_Options_PrintCheckbox("Force New Blood Effect", true, cl_particles_blood_bloodhack.integer);
-       M_Options_PrintCheckbox("    Lightning Polygons", true, cl_beams_polygons.integer);
-       M_Options_PrintCheckbox("Lightning Smooth Sweep", true, cl_beams_relative.integer);
+       M_Options_PrintCheckbox("     Polygon Lightning", true, cl_beams_polygons.integer);
+       M_Options_PrintCheckbox("Smooth Sweep Lightning", true, cl_beams_instantaimhack.integer);
+       M_Options_PrintCheckbox(" Waist-level Lightning", true, cl_beams_quakepositionhack.integer);
        M_Options_PrintCheckbox("   Lightning End Light", true, cl_beams_lightatend.integer);
        M_Options_PrintSlider(  "   Lightning Thickness", cl_beams_polygons.integer, r_lightningbeam_thickness.integer, 1, 10);
        M_Options_PrintSlider(  "      Lightning Scroll", cl_beams_polygons.integer, r_lightningbeam_scroll.integer, 0, 10);
index 68f6b8f..eabf768 100644 (file)
@@ -269,12 +269,14 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r
        for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
        {
                const beam_t *b = cl.beams + surfacelist[surfacelistindex];
-               vec3_t beamdir, right, up, offset;
+               vec3_t beamdir, right, up, offset, start, end;
                float length, t1, t2;
+               
+               CL_Beam_CalculatePositions(b, start, end);
 
                // calculate beam direction (beamdir) vector and beam length
                // get difference vector
-               VectorSubtract(b->end, b->start, beamdir);
+               VectorSubtract(end, start, beamdir);
                // find length of difference vector
                length = sqrt(DotProduct(beamdir, beamdir));
                // calculate scale to make beamdir a unit vector (normalized)
@@ -284,7 +286,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r
 
                // calculate up vector such that it points toward viewer, and rotates around the beamdir
                // get direction from start of beam to viewer
-               VectorSubtract(r_view.origin, b->start, up);
+               VectorSubtract(r_view.origin, start, up);
                // remove the portion of the vector that moves along the beam
                // (this leaves only a vector pointing directly away from the beam)
                t1 = -DotProduct(up, beamdir);
@@ -296,7 +298,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r
                VectorNormalize(up);
 
                // calculate T coordinate scrolling (start and end texcoord along the beam)
-               t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(b->start, beamdir);
+               t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(start, beamdir);
                t1 = t1 - (int) t1;
                t2 = t1 + beamrepeatscale * length;
 
@@ -313,15 +315,15 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r
 
                // polygon 1, verts 0-3
                VectorScale(right, r_lightningbeam_thickness.value, offset);
-               R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, b->start, b->end, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, start, end, offset);
                // polygon 2, verts 4-7
                VectorAdd(right, up, offset);
                VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
-               R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, b->start, b->end, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, start, end, offset);
                // polygon 3, verts 8-11
                VectorSubtract(right, up, offset);
                VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
-               R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, b->start, b->end, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, start, end, offset);
                R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 0, t1, t2);
                R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 8, t1 + 0.33, t2 + 0.33);
                R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 16, t1 + 0.66, t2 + 0.66);
@@ -338,11 +340,11 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r
        }
 }
 
+extern cvar_t cl_beams_polygons;
 void R_DrawLightningBeams(void)
 {
        int i;
        beam_t *b;
-       vec3_t org;
 
        if (!cl_beams_polygons.integer)
                return;
@@ -350,10 +352,17 @@ void R_DrawLightningBeams(void)
        beamrepeatscale = 1.0f / r_lightningbeam_repeatdistance.value;
        for (i = 0, b = cl.beams;i < cl.num_beams;i++, b++)
        {
-               if (b->model && b->endtime >= r_refdef.time && b->lightning)
+               if (b->model && b->lightning)
                {
-                       VectorAdd(b->start, b->end, org);
-                       VectorScale(org, 0.5f, org);
+                       vec3_t org, start, end, dir;
+                       vec_t dist;
+                       CL_Beam_CalculatePositions(b, start, end);
+                       // calculate the nearest point on the line (beam) for depth sorting
+                       VectorSubtract(end, start, dir);
+                       dist = (DotProduct(r_view.origin, dir) - DotProduct(start, dir)) / (DotProduct(end, dir) - DotProduct(start, dir));
+                       dist = bound(0, dist, 1);
+                       VectorLerp(start, dist, end, org);
+                       // now we have the nearest point on the line, so sort with it
                        R_MeshQueue_AddTransparent(org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
                }
        }
diff --git a/todo b/todo
index e692b29..63b4e54 100644 (file)
--- a/todo
+++ b/todo
@@ -56,6 +56,7 @@
 0 bug darkplaces server: the lava+func_trains room of r1m5 is leaving items floating in the air - r1m5 is Towers of Wrath, in episode of Dissolution of Eternity, aka rogue (maichal)
 0 bug darkplaces video: generate 1024 color gamma ramps for glx on Quadro, right now hardware gamma is being disabled on these cards because they use 1024 color ramps, not 256 (div0)
 0 bug darkplaces wgl client: during video mode setup, sometimes another application's window becomes permanently top most, not darkplaces' fullscreen window, why? (tZork)
+0 bug darkplaces wgl client: hardware gamma is being retried every frame for unknown reasons, this is SEVERELY impacting framerates on win2k/xp (Jago)
 0 bug darkplaces windows sound: freezing on exit sometimes when freeing sound buffer during sound shutdown (Black)
 0 bug dpmod: allow selection of weapons with secondary ammo but no primary ammo, and switch away if trying to fire primary ammo you don't have (romi)
 0 bug dpmod: chthon stops attacking in coop if shot enough
 0 change darkplaces client: disable all possible 'cheat' things unless -developer is given on commandline, this includes r_show*, r_test, gl_lightmaps, r_fullbright
 0 change darkplaces client: get image sizes from .lmp files if present
 0 change darkplaces client: hardcode sbar image sizes so they can be replaced with higher quality images
+0 change darkplaces client: modify cl_particles_quake to make all the engine dlights be white and look as much like quake as possible (Jago)
 0 change darkplaces client: particles shouldn't be using contents checks to decide whether to die, they should use movement traces
 0 change darkplaces client: restrict wateralpha and such cvars according to what is permitted in qw serverinfo?
+0 change darkplaces client: turn off coronas on dlights (Jago)
 0 change darkplaces extensions: edit FRIK_FILE documentation to mention that fgets uses its own separate buffer, so only one fgets can be done at a time without uzing strzone, but that darkplaces uses standard tempstrings for fgets (it doesn't - change it!) and mention DP_QC_MULTIPLETEMPSTRINGS (FrikaC)
 0 change darkplaces extensions: edit FRIK_FILE documentation to mention that strcat uses its own separate buffer, and that a = strcat(a, b);a = strcat(a, c); works correctly despite this, also mention that in DP strcat uses standard tempstrings, and mention DP_QC_MULTIPLETEMPSTRINGS (FrikaC)
 0 change darkplaces general: make r_speeds 2 show timings for other subsystems such as client, sound, server, network (Carni)
 2 feature darkplaces loader: add support for fuhquake naming of map textures (textures/start/quake.tga style)
 2 feature darkplaces menu: add some basic graphics/effects options profiles so that people can choose profiles like "Classic", "Modern", "Excessive", "Realistic", or any other profiles that make sense, may also need to reorganize the graphics/effects options menus to be a bit less confusing (Tron)
 2 feature darkplaces menu: implement menu_clearkeyconfig and menu_keyconfig and the corresponding menu (diGGer)
+2 feature darkplaces menu: new game custom level/mod menu, which allows you to choose a mod and browse through maps and choose starting skill, by default it would have the current mod selected and start selected (Jago)
 2 feature darkplaces model: add model_exportobj console command to allow exporting a specified model as .obj (Randy)
 2 feature darkplaces physics: DP_SV_QCPHYSICS extension, calls SV_PhysicsQC function, which replaces the entire SV_Physics C function, calling all thinks and physics and everything (Urre)
 2 feature darkplaces protocol: .float bulge; field which makes an entity larger by moving vertices along their normals, well known as the fatboy mutator in Unreal Tournament (Wazat)