renamed brush model pvs stuff to be in brush struct instead of brushq1 and brushq3...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 25 Feb 2004 18:42:31 +0000 (18:42 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 25 Feb 2004 18:42:31 +0000 (18:42 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3926 d7cf8633-e32d-0410-b094-e92efae38249

gl_rsurf.c
model_brush.c
model_shared.h
r_light.c
r_shadow.c
todo

index 75daf71..2ff6925 100644 (file)
@@ -2302,7 +2302,7 @@ void R_Q3BSP_DrawSky(entity_render_t *ent)
        if (r_drawcollisionbrushes.integer < 2)
        {
                Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
-               if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
+               if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                {
                        if (r_q3bsp_framecount != r_framecount)
                        {
@@ -2333,7 +2333,7 @@ void R_Q3BSP_Draw(entity_render_t *ent)
        if (r_drawcollisionbrushes.integer < 2)
        {
                Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
-               if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
+               if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                {
                        if (r_q3bsp_framecount != r_framecount)
                        {
@@ -2384,7 +2384,7 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
                lightmaxs[0] = relativelightorigin[0] + lightradius;
                lightmaxs[1] = relativelightorigin[1] + lightradius;
                lightmaxs[2] = relativelightorigin[2] + lightradius;
-               //if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
+               //if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                //      R_Q3BSP_RecursiveWorldNode(ent, model->brushq3.data_nodes, modelorg, pvs, ++markframe);
                //else
                        for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
@@ -2420,7 +2420,7 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t
                lightmaxs[0] = relativelightorigin[0] + lightradius;
                lightmaxs[1] = relativelightorigin[1] + lightradius;
                lightmaxs[2] = relativelightorigin[2] + lightradius;
-               //if (ent == &cl_entities[0].render && model->brushq3.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
+               //if (ent == &cl_entities[0].render && model->brush.num_pvsclusters && !r_novis.integer && (pvs = model->brush.GetPVS(model, modelorg)))
                //      R_Q3BSP_RecursiveWorldNode(ent, model->brushq3.data_nodes, modelorg, pvs, ++markframe);
                //else
                        for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
index 1f03498..6940f01 100644 (file)
@@ -1985,10 +1985,10 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
        loadmodel->brushq1.data_leafs = out;
        loadmodel->brushq1.num_leafs = count;
        // get visleafs from the submodel data
-       loadmodel->brushq1.num_pvsclusters = loadmodel->brushq1.submodels[0].visleafs;
-       loadmodel->brushq1.num_pvsclusterbytes = (loadmodel->brushq1.num_pvsclusters+7)>>3;
-       loadmodel->brushq1.data_pvsclusters = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.num_pvsclusters * loadmodel->brushq1.num_pvsclusterbytes);
-       memset(loadmodel->brushq1.data_pvsclusters, 0xFF, loadmodel->brushq1.num_pvsclusters * loadmodel->brushq1.num_pvsclusterbytes);
+       loadmodel->brush.num_pvsclusters = loadmodel->brushq1.submodels[0].visleafs;
+       loadmodel->brush.num_pvsclusterbytes = (loadmodel->brush.num_pvsclusters+7)>>3;
+       loadmodel->brush.data_pvsclusters = Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_pvsclusters * loadmodel->brush.num_pvsclusterbytes);
+       memset(loadmodel->brush.data_pvsclusters, 0xFF, loadmodel->brush.num_pvsclusters * loadmodel->brush.num_pvsclusterbytes);
 
        for ( i=0 ; i<count ; i++, in++, out++)
        {
@@ -2012,7 +2012,7 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
                }
 
                out->clusterindex = i - 1;
-               if (out->clusterindex >= loadmodel->brushq1.num_pvsclusters)
+               if (out->clusterindex >= loadmodel->brush.num_pvsclusters)
                        out->clusterindex = -1;
 
                p = LittleLong(in->visofs);
@@ -2022,7 +2022,7 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
                        if (p >= loadmodel->brushq1.num_compressedpvs)
                                Con_Printf("Mod_Q1BSP_LoadLeafs: invalid visofs\n");
                        else
-                               Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, loadmodel->brushq1.data_pvsclusters + out->clusterindex * loadmodel->brushq1.num_pvsclusterbytes, loadmodel->brushq1.data_pvsclusters + (out->clusterindex + 1) * loadmodel->brushq1.num_pvsclusterbytes);
+                               Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, loadmodel->brush.data_pvsclusters + out->clusterindex * loadmodel->brush.num_pvsclusterbytes, loadmodel->brush.data_pvsclusters + (out->clusterindex + 1) * loadmodel->brush.num_pvsclusterbytes);
                }
 
                for (j = 0;j < 4;j++)
@@ -2749,7 +2749,7 @@ static void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
        if (((mleaf_t *)node)->clusterindex >= 0)
        {
                int i;
-               qbyte *pvs = model->brushq1.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
+               qbyte *pvs = model->brush.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
                for (i = 0;i < pvsbytes;i++)
                        pvsbuffer[i] |= pvs[i];
        }
@@ -2781,7 +2781,7 @@ static qbyte *Mod_Q1BSP_GetPVS(model_t *model, const vec3_t p)
        while (node->plane)
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
        if (((mleaf_t *)node)->clusterindex >= 0)
-               return model->brushq1.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
+               return model->brush.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
        else
                return NULL;
 }
@@ -4497,15 +4497,15 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
                int i;
                // unvised maps often have cluster indices even without pvs, so check
                // leafs to find real number of clusters
-               loadmodel->brushq3.num_pvsclusters = 1;
+               loadmodel->brush.num_pvsclusters = 1;
                for (i = 0;i < loadmodel->brushq3.num_leafs;i++)
-                       loadmodel->brushq3.num_pvsclusters = min(loadmodel->brushq3.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
+                       loadmodel->brush.num_pvsclusters = min(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
 
                // create clusters
-               loadmodel->brushq3.num_pvsclusterbytes = (loadmodel->brushq3.num_pvsclusters + 7) / 8;
-               totalchains = loadmodel->brushq3.num_pvsclusterbytes * loadmodel->brushq3.num_pvsclusters;
-               loadmodel->brushq3.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
-               memset(loadmodel->brushq3.data_pvsclusters, 0xFF, totalchains);
+               loadmodel->brush.num_pvsclusterbytes = (loadmodel->brush.num_pvsclusters + 7) / 8;
+               totalchains = loadmodel->brush.num_pvsclusterbytes * loadmodel->brush.num_pvsclusters;
+               loadmodel->brush.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
+               memset(loadmodel->brush.data_pvsclusters, 0xFF, totalchains);
                return;
        }
 
@@ -4513,16 +4513,16 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
        if (l->filelen < 9)
                Host_Error("Mod_Q3BSP_LoadPVS: funny lump size in %s",loadmodel->name);
 
-       loadmodel->brushq3.num_pvsclusters = LittleLong(in->numclusters);
-       loadmodel->brushq3.num_pvsclusterbytes = LittleLong(in->chainlength);
-       if (loadmodel->brushq3.num_pvsclusterbytes < ((loadmodel->brushq3.num_pvsclusters + 7) / 8))
-               Host_Error("Mod_Q3BSP_LoadPVS: (chainlength = %i) < ((numclusters = %i) + 7) / 8\n", loadmodel->brushq3.num_pvsclusterbytes, loadmodel->brushq3.num_pvsclusters);
-       totalchains = loadmodel->brushq3.num_pvsclusterbytes * loadmodel->brushq3.num_pvsclusters;
+       loadmodel->brush.num_pvsclusters = LittleLong(in->numclusters);
+       loadmodel->brush.num_pvsclusterbytes = LittleLong(in->chainlength);
+       if (loadmodel->brush.num_pvsclusterbytes < ((loadmodel->brush.num_pvsclusters + 7) / 8))
+               Host_Error("Mod_Q3BSP_LoadPVS: (chainlength = %i) < ((numclusters = %i) + 7) / 8\n", loadmodel->brush.num_pvsclusterbytes, loadmodel->brush.num_pvsclusters);
+       totalchains = loadmodel->brush.num_pvsclusterbytes * loadmodel->brush.num_pvsclusters;
        if (l->filelen < totalchains + (int)sizeof(*in))
-               Host_Error("Mod_Q3BSP_LoadPVS: lump too small ((numclusters = %i) * (chainlength = %i) + sizeof(q3dpvs_t) == %i bytes, lump is %i bytes)\n", loadmodel->brushq3.num_pvsclusters, loadmodel->brushq3.num_pvsclusterbytes, totalchains + sizeof(*in), l->filelen);
+               Host_Error("Mod_Q3BSP_LoadPVS: lump too small ((numclusters = %i) * (chainlength = %i) + sizeof(q3dpvs_t) == %i bytes, lump is %i bytes)\n", loadmodel->brush.num_pvsclusters, loadmodel->brush.num_pvsclusterbytes, totalchains + sizeof(*in), l->filelen);
 
-       loadmodel->brushq3.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
-       memcpy(loadmodel->brushq3.data_pvsclusters, (qbyte *)(in + 1), totalchains);
+       loadmodel->brush.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
+       memcpy(loadmodel->brush.data_pvsclusters, (qbyte *)(in + 1), totalchains);
 }
 
 static void Mod_Q3BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, vec_t radius)
@@ -5157,7 +5157,7 @@ static int Mod_Q3BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
        int clusterindex, side, nodestackindex = 0;
        q3mnode_t *node, *nodestack[1024];
        node = model->brushq3.data_nodes;
-       if (!loadmodel->brushq3.num_pvsclusters)
+       if (!loadmodel->brush.num_pvsclusters)
                return true;
        for (;;)
        {
@@ -5182,9 +5182,9 @@ static int Mod_Q3BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
                        // leaf - check cluster bit
                        clusterindex = ((q3mleaf_t *)node)->clusterindex;
 #if 0
-                       if (clusterindex >= loadmodel->brushq3.num_pvsclusters)
+                       if (clusterindex >= loadmodel->brush.num_pvsclusters)
                        {
-                               Con_Printf("%i >= %i\n", clusterindex, loadmodel->brushq3.num_pvsclusters);
+                               Con_Printf("%i >= %i\n", clusterindex, loadmodel->brush.num_pvsclusters);
                                return true;
                        }
 #endif
@@ -5216,7 +5216,7 @@ static qbyte *Mod_Q3BSP_GetPVS(model_t *model, const vec3_t p)
        while (node->plane)
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
        if (((q3mleaf_t *)node)->clusterindex >= 0)
-               return model->brushq3.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brushq3.num_pvsclusterbytes;
+               return model->brush.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
        else
                return NULL;
 }
@@ -5241,7 +5241,7 @@ static void Mod_Q3BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
        if (((q3mleaf_t *)node)->clusterindex >= 0)
        {
                int i;
-               qbyte *pvs = model->brushq1.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
+               qbyte *pvs = model->brush.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
                for (i = 0;i < pvsbytes;i++)
                        pvsbuffer[i] |= pvs[i];
        }
@@ -5251,9 +5251,9 @@ static void Mod_Q3BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
 //of the given point.
 static int Mod_Q3BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
 {
-       int bytes = model->brushq3.num_pvsclusterbytes;
+       int bytes = model->brush.num_pvsclusterbytes;
        bytes = min(bytes, pvsbufferlength);
-       if (r_novis.integer || !loadmodel->brushq3.num_pvsclusters)
+       if (r_novis.integer || !loadmodel->brush.num_pvsclusters)
        {
                memset(pvsbuffer, 0xFF, bytes);
                return bytes;
index 268873c..8633963 100644 (file)
@@ -165,6 +165,15 @@ typedef struct model_brush_s
        // number of submodels in this map (just used by server to know how many
        // submodels to load)
        int numsubmodels;
+
+       // pvs
+       int num_pvsclusters;
+       int num_pvsclusterbytes;
+       unsigned char *data_pvsclusters;
+       // example
+       //pvschain = model->brush.data_pvsclusters + mycluster * model->brush.num_pvsclusterbytes;
+       //if (pvschain[thatcluster >> 3] & (1 << (thatcluster & 7)))
+
        // common functions
        int (*SuperContentsFromNativeContents)(struct model_s *model, int nativecontents);
        int (*NativeContentsFromSuperContents)(struct model_s *model, int supercontents);
@@ -232,9 +241,6 @@ typedef struct model_brushq1_s
 
        int                             num_compressedpvs;
        qbyte                   *data_compressedpvs;
-       int num_pvsclusters;
-       int num_pvsclusterbytes;
-       unsigned char *data_pvsclusters;
 
        int                             num_lightdata;
        qbyte                   *lightdata;
@@ -516,14 +522,6 @@ typedef struct model_brushq3_s
        int num_lightgrid_dimensions[3];
        // transform modelspace coordinates to lightgrid index
        matrix4x4_t num_lightgrid_indexfromworld;
-
-       // pvs
-       int num_pvsclusters;
-       int num_pvsclusterbytes;
-       unsigned char *data_pvsclusters;
-       // example
-       //pvschain = model->brushq3.data_pvsclusters + mycluster * model->brushq3.num_pvsclusterbytes;
-       //if (pvschain[thatcluster >> 3] & (1 << (thatcluster & 7)))
 }
 model_brushq3_t;
 
index 89f36ad..b3ec3a5 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -295,7 +295,7 @@ void R_MarkLights(entity_render_t *ent)
                        lightpvsbytes = 0;
                        if (r_vismarklights.integer && ent->model->brush.FatPVS)
                                lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs));
-                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.num_pvsclusters));
+                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brush.num_pvsclusters));
                }
        }
 }
index f5d07e3..afd2a85 100644 (file)
@@ -2051,11 +2051,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                        SETPVSBIT(lightpvs, leaf->clusterindex);
 
                        // make a cluster list for fast visibility checking during rendering
-                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq3.num_pvsclusters;i++)
+                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                if (CHECKPVSBIT(lightpvs, i))
                                        e->numclusters++;
                        e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq3.num_pvsclusters;i++)
+                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                if (CHECKPVSBIT(lightpvs, i))
                                        e->clusterindices[e->numclusters++] = i;
 
@@ -2141,11 +2141,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                Mem_Free(bytesurfacepvs);
        
                                // make a cluster list for fast visibility checking during rendering
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
                                                e->numclusters++;
                                e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
                                                e->clusterindices[e->numclusters++] = i;
                        }
@@ -2177,11 +2177,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                SETPVSBIT(lightpvs, leaf->clusterindex);
 
                                // make a cluster list for fast visibility checking during rendering
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
                                                e->numclusters++;
                                e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
-                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brush.num_pvsclusters;i++)
                                        if (CHECKPVSBIT(lightpvs, i))
                                                e->clusterindices[e->numclusters++] = i;
                        }
diff --git a/todo b/todo
index 34c163c..630bce2 100644 (file)
--- a/todo
+++ b/todo
@@ -34,6 +34,8 @@
 -n darkplaces: segfault reading memory in windows when starting a new server from menu (yummyluv)
 -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv)
 -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv)
+d darkplaces: make bounce check for fabs(dotproduct)<60 velocity, not dotproduct<60, so now an explosion above gibs will cause them to bounce up into the air 
+d darkplaces: merge pvs info for all brush model formats
 d darkplaces: figure out why fullbrights are black on models (romi)
 0 darkplaces: add support for .float corona and corona_radius to control corona intensity and radius on dlights (Electro) 
 0 darkplaces: add "skin" and "pflags" parsing to light entity loader in rtlights mode (Electro)  
@@ -174,7 +176,7 @@ d darkplaces: add DP_LITSUPPORT extension and document it
 0 darkplaces: add sv_gameplayfix_noairborncorpse cvar (default 1)
 0 darkplaces: add sv_gameplayfix_stepwhilejumping cvar (default 1), note that sv_jumpstep must also be on to enable this
 0 darkplaces: add sv_gameplayfix_swiminbmodels cvar (default 1)
-0 darkplaces: add svc_setanglefloat and DP_SVC_SETANGLEFLOAT extension (FrikaC, SeienAbunae)
+0 darkplaces: add svc_setanglefloat and DP_SVC_SETANGLEFLOAT extension (FrikaC, SeienAbunae, mashakos, RenegadeC)
 0 darkplaces: add te_flamejet builtin and add extension (Supajoe)
 0 darkplaces: add vid_vsync cvar and also to options menu (metlslime)
 0 darkplaces: alias layers should have a shadow volume pass so that nodraw textures don't cast a shadow (Electro)
@@ -274,7 +276,7 @@ d darkplaces: q1bsp trace bug: scrags frequently fly through ceilings - this nee
 0 sv_user.qc: figure out why looking up/down slows movement and fix it (Vermeulen)
 1 darkplaces: add DP_CLIENTCAMERA extension (.entity clientcamera; sets which entity the client views from) (Wazat for Battlemech, SeienAbunae)
 1 darkplaces: add DP_EF_CLIENTLOCKANGLES extension (prevents client from turning view, takes angles from entity) (Wazat for Battlemech, SeienAbunae)
-1 darkplaces: add DP_EF_PRECISEANGLES extension (sends short angles instead of byte) (Wazat for Battlemech)
+1 darkplaces: add DP_EF_PRECISEANGLES extension (sends short angles instead of byte) (Wazat for Battlemech, FrikaC, mashakos, RenegadeC)
 1 darkplaces: add DP_QC_ENDFRAME extension/documentation and post it on wiki (tell Uffe, SeienAbunae)
 1 darkplaces: add DP_SV_READCLIENTINPUT extension (.vector clientinput; works like .movement but for mouse or any other similar controllers) (Wazat for Battlemech, FrikaC, SeienAbunae)
 1 darkplaces: add EndGame function (called on server shutdown or level change) (SeienAbunae, Nexuiz)