]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_main.c
optimized SHOWLMP code (only used by Nehahra) to not eat any CPU time
[xonotic/darkplaces.git] / cl_main.c
index a159d68490a0bc71038bf0632b7efc1296ab415d..79a6a1f2f87d3e97c8be8b02523cbb184c2f6784 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "csprogs.h"
 #include "r_shadow.h"
 #include "libcurl.h"
+#include "snd_main.h"
 
 // we need to declare some mouse variables here, because the menu system
 // references them even when on a unix system.
@@ -52,7 +53,7 @@ cvar_t m_side = {CVAR_SAVE, "m_side","0.8","mouse side speed multiplier"};
 cvar_t freelook = {CVAR_SAVE, "freelook", "1","mouse controls pitch instead of forward/back"};
 
 cvar_t cl_autodemo = {CVAR_SAVE, "cl_autodemo", "0", "records every game played, using the date/time and map name to name the demo file" };
-cvar_t cl_autodemo_nameformat = {CVAR_SAVE, "cl_autodemo_nameformat", "%Y-%m-%d_%H-%M", "The format of the cl_autodemo filename, followed by the map name" };
+cvar_t cl_autodemo_nameformat = {CVAR_SAVE, "cl_autodemo_nameformat", "autodemos/%Y-%m-%d_%H-%M", "The format of the cl_autodemo filename, followed by the map name" };
 
 cvar_t r_draweffects = {0, "r_draweffects", "1","renders temporary sprite effects"};
 
@@ -110,6 +111,14 @@ void CL_ClearState(void)
        // reset the view zoom interpolation
        cl.mviewzoom[0] = cl.mviewzoom[1] = 1;
 
+       // enable rendering of the world and such
+       cl.csqc_vidvars.drawworld = true;
+       cl.csqc_vidvars.drawenginesbar = true;
+       cl.csqc_vidvars.drawcrosshair = true;
+
+       // set up the float version of the stats array for easier access to float stats
+       cl.statsf = (float *)cl.stats;
+
        cl.num_entities = 0;
        cl.num_static_entities = 0;
        cl.num_temp_entities = 0;
@@ -125,6 +134,7 @@ void CL_ClearState(void)
        cl.max_lightstyle = MAX_LIGHTSTYLES;
        cl.max_brushmodel_entities = MAX_EDICTS;
        cl.max_particles = MAX_PARTICLES;
+       cl.max_showlmps = 0;
 
 // COMMANDLINEOPTION: Client: -particles <number> changes maximum number of particles at once, default 32768
        i = COM_CheckParm ("-particles");
@@ -149,6 +159,7 @@ void CL_ClearState(void)
        cl.lightstyle = (lightstyle_t *)Mem_Alloc(cls.levelmempool, cl.max_lightstyle * sizeof(lightstyle_t));
        cl.brushmodel_entities = (int *)Mem_Alloc(cls.levelmempool, cl.max_brushmodel_entities * sizeof(int));
        cl.particles = (particle_t *) Mem_Alloc(cls.levelmempool, cl.max_particles * sizeof(particle_t));
+       cl.showlmps = NULL;
 
        // LordHavoc: have to set up the baseline info for alpha and other stuff
        for (i = 0;i < cl.max_entities;i++)
@@ -192,6 +203,9 @@ void CL_ClearState(void)
        // mark all frames invalid for delta
        memset(cl.qw_deltasequence, -1, sizeof(cl.qw_deltasequence));
 
+       // set bestweapon data back to Quake data
+       IN_BestWeapon_ResetData();
+
        CL_Screen_NewMap();
 }
 
@@ -338,9 +352,9 @@ void CL_Disconnect(void)
                        Con_DPrint("Sending clc_disconnect\n");
                        MSG_WriteByte(&buf, clc_disconnect);
                }
-               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol);
-               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol);
-               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol);
+               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, 10000, false);
+               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, 10000, false);
+               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, 10000, false);
                NetConn_Close(cls.netcon);
                cls.netcon = NULL;
        }
@@ -432,7 +446,49 @@ static void CL_PrintEntities_f(void)
                        modelname = ent->render.model->name;
                else
                        modelname = "--no model--";
-               Con_Printf("%3i: %-25s:%4i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", i, modelname, ent->render.frame, (int) ent->state_current.origin[0], (int) ent->state_current.origin[1], (int) ent->state_current.origin[2], (int) ent->state_current.angles[0] % 360, (int) ent->state_current.angles[1] % 360, (int) ent->state_current.angles[2] % 360, ent->render.scale, ent->render.alpha);
+               Con_Printf("%3i: %-25s:%4i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", i, modelname, ent->render.frame2, (int) ent->state_current.origin[0], (int) ent->state_current.origin[1], (int) ent->state_current.origin[2], (int) ent->state_current.angles[0] % 360, (int) ent->state_current.angles[1] % 360, (int) ent->state_current.angles[2] % 360, ent->render.scale, ent->render.alpha);
+       }
+}
+
+/*
+===============
+CL_ModelIndexList_f
+
+List information on all models in the client modelindex
+===============
+*/
+static void CL_ModelIndexList_f(void)
+{
+       int i = 1;
+
+       // Print Header
+       Con_Printf("%3s: %-30s %-8s %-8s\n", "ID", "Name", "Type", "Triangles");
+
+       while(cl.model_precache[i] && i != MAX_MODELS)
+       { // Valid Model
+               if(cl.model_precache[i]->loaded || cl.model_precache[i]->isworldmodel)
+                       Con_Printf("%3i: %-30s %-8s %-10i\n", i, cl.model_precache[i]->name, cl.model_precache[i]->modeldatatypestring, cl.model_precache[i]->surfmesh.num_triangles);
+               else
+                       Con_Printf("%3i: %-30s %-30s\n", i, cl.model_precache[i]->name, "--no local model found--");
+               i++;
+       }
+}
+
+/*
+===============
+CL_SoundIndexList_f
+
+List all sounds in the client soundindex
+===============
+*/
+static void CL_SoundIndexList_f(void)
+{
+       int i = 1;
+
+       while(cl.sound_precache[i] && i != MAX_SOUNDS)
+       { // Valid Sound
+               Con_Printf("%i : %s\n", i, cl.sound_precache[i]->name);
+               i++;
        }
 }
 
@@ -503,7 +559,7 @@ static float CL_LerpPoint(void)
 {
        float f;
 
-       if (cl_nettimesyncmode.integer == 3)
+       if (cl_nettimesyncboundmode.integer == 1)
                cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]);
 
        // LordHavoc: lerp in listen games as the server is being capped below the client (usually)
@@ -783,7 +839,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
 {
        const matrix4x4_t *matrix;
        matrix4x4_t blendmatrix, tempmatrix, matrix2;
-       int j, k, l;
+       int j, k, l, frame;
        float origin[3], angles[3], delta[3], lerp, d;
        entity_t *t;
        model_t *model;
@@ -799,34 +855,29 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        e->render.flags = e->state_current.flags;
        e->render.effects = e->state_current.effects;
        VectorScale(e->state_current.colormod, (1.0f / 32.0f), e->render.colormod);
+       e->render.entitynumber = e - cl.entities;
        if (e->state_current.flags & RENDER_COLORMAPPED)
        {
-               int cb;
                unsigned char *cbcolor;
                e->render.colormap = e->state_current.colormap;
-               cb = (e->render.colormap & 0xF) << 4;cb += (cb >= 128 && cb < 224) ? 4 : 12;
-               cbcolor = (unsigned char *) (&palette_complete[cb]);
+               cbcolor = (unsigned char *) (&palette_pantscolormap[e->render.colormap & 0xF]);
                e->render.colormap_pantscolor[0] = cbcolor[0] * (1.0f / 255.0f);
                e->render.colormap_pantscolor[1] = cbcolor[1] * (1.0f / 255.0f);
                e->render.colormap_pantscolor[2] = cbcolor[2] * (1.0f / 255.0f);
-               cb = (e->render.colormap & 0xF0);cb += (cb >= 128 && cb < 224) ? 4 : 12;
-               cbcolor = (unsigned char *) (&palette_complete[cb]);
+               cbcolor = (unsigned char *) (&palette_shirtcolormap[(e->render.colormap & 0xF0) >> 4]);
                e->render.colormap_shirtcolor[0] = cbcolor[0] * (1.0f / 255.0f);
                e->render.colormap_shirtcolor[1] = cbcolor[1] * (1.0f / 255.0f);
                e->render.colormap_shirtcolor[2] = cbcolor[2] * (1.0f / 255.0f);
        }
-       else if (e->state_current.colormap && cl.scores != NULL)
+       else if (e->state_current.colormap && cl.scores != NULL && e->state_current.colormap <= cl.maxclients)
        {
-               int cb;
                unsigned char *cbcolor;
                e->render.colormap = cl.scores[e->state_current.colormap - 1].colors; // color it
-               cb = (e->render.colormap & 0xF) << 4;cb += (cb >= 128 && cb < 224) ? 4 : 12;
-               cbcolor = (unsigned char *) (&palette_complete[cb]);
+               cbcolor = (unsigned char *) (&palette_pantscolormap[e->render.colormap & 0xF]);
                e->render.colormap_pantscolor[0] = cbcolor[0] * (1.0f / 255.0f);
                e->render.colormap_pantscolor[1] = cbcolor[1] * (1.0f / 255.0f);
                e->render.colormap_pantscolor[2] = cbcolor[2] * (1.0f / 255.0f);
-               cb = (e->render.colormap & 0xF0);cb += (cb >= 128 && cb < 224) ? 4 : 12;
-               cbcolor = (unsigned char *) (&palette_complete[cb]);
+               cbcolor = (unsigned char *) (&palette_shirtcolormap[(e->render.colormap & 0xF0) >> 4]);
                e->render.colormap_shirtcolor[0] = cbcolor[0] * (1.0f / 255.0f);
                e->render.colormap_shirtcolor[1] = cbcolor[1] * (1.0f / 255.0f);
                e->render.colormap_shirtcolor[2] = cbcolor[2] * (1.0f / 255.0f);
@@ -878,7 +929,10 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        else if (e->render.flags & RENDER_VIEWMODEL)
        {
                // view-relative entity (guns and such)
-               matrix = &viewmodelmatrix;
+               if (e->render.effects & EF_NOGUNBOB)
+                       matrix = &r_view.matrix; // really attached to view
+               else
+                       matrix = &viewmodelmatrix; // attached to gun bob matrix
        }
        else
        {
@@ -922,21 +976,24 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        }
 
        // model setup and some modelflags
-       if(e->state_current.modelindex < MAX_MODELS)
+       frame = e->state_current.frame;
+       if (e->state_current.modelindex < MAX_MODELS)
                e->render.model = cl.model_precache[e->state_current.modelindex];
+       else
+               e->render.model = NULL;
        if (e->render.model)
        {
+               if (e->render.skinnum >= e->render.model->numskins)
+                       e->render.skinnum = 0;
+               if (frame >= e->render.model->numframes)
+                       frame = 0;
+               // models can set flags such as EF_ROCKET
+               // this 0xFF800000 mask is EF_NOMODELFLAGS plus all the higher EF_ flags such as EF_ROCKET
+               if (!(e->render.effects & 0xFF800000))
+                       e->render.effects |= e->render.model->effects;
                // if model is alias or this is a tenebrae-like dlight, reverse pitch direction
                if (e->render.model->type == mod_alias)
                        angles[0] = -angles[0];
-               if ((e->render.model->flags & EF_ROTATE) && (!e->state_current.tagentity && !(e->render.flags & RENDER_VIEWMODEL)))
-               {
-                       angles[1] = ANGLEMOD(100*cl.time);
-                       if (cl_itembobheight.value)
-                               origin[2] += (cos(cl.time * cl_itembobspeed.value * (2.0 * M_PI)) + 1.0) * 0.5 * cl_itembobheight.value;
-               }
-               // transfer certain model flags to effects
-               e->render.effects |= e->render.model->flags2 & (EF_FULLBRIGHT | EF_ADDITIVE);
                if ((e->render.effects & EF_SELECTABLE) && cl.cmd.cursor_entitynumber == e->state_current.number)
                        VectorScale(e->render.colormod, 2, e->render.colormod);
        }
@@ -944,8 +1001,15 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        else if (e->state_current.lightpflags & PFLAGS_FULLDYNAMIC)
                angles[0] = -angles[0];
 
+       if ((e->render.effects & EF_ROTATE) && !(e->render.flags & RENDER_VIEWMODEL))
+       {
+               angles[1] = ANGLEMOD(100*cl.time);
+               if (cl_itembobheight.value)
+                       origin[2] += (cos(cl.time * cl_itembobspeed.value * (2.0 * M_PI)) + 1.0) * 0.5 * cl_itembobheight.value;
+       }
+
        // animation lerp
-       if (e->render.frame2 == e->state_current.frame)
+       if (e->render.frame2 == frame)
        {
                // update frame lerp fraction
                e->render.framelerp = 1;
@@ -963,7 +1027,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                // begin a new frame lerp
                e->render.frame1 = e->render.frame2;
                e->render.frame1time = e->render.frame2time;
-               e->render.frame = e->render.frame2 = e->state_current.frame;
+               e->render.frame2 = frame;
                e->render.frame2time = cl.time;
                e->render.framelerp = 0;
        }
@@ -1003,6 +1067,8 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
         && !(e->render.flags & RENDER_VIEWMODEL)
         && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
                e->render.flags |= RENDER_SHADOW;
+       if (e->render.flags & RENDER_VIEWMODEL)
+               e->render.flags |= RENDER_NOSELFSHADOW;
 }
 
 // creates light and trails from an entity
@@ -1026,7 +1092,7 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
        // entity is in the world...
        trailtype = EFFECT_NONE;
        // LordHavoc: if the entity has no effects, don't check each
-       if (e->render.effects & (EF_BRIGHTFIELD | EF_FLAME | EF_STARDUST | EF_FLAG1QW | EF_FLAG2QW))
+       if (e->render.effects & (EF_BRIGHTFIELD | EF_FLAME | EF_STARDUST))
        {
                if (e->render.effects & EF_BRIGHTFIELD)
                {
@@ -1039,40 +1105,41 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
                        CL_ParticleTrail(EFFECT_EF_FLAME, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true);
                if (e->render.effects & EF_STARDUST)
                        CL_ParticleTrail(EFFECT_EF_STARDUST, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true);
-               if (e->render.effects & (EF_FLAG1QW | EF_FLAG2QW))
-               {
-                       // these are only set on player entities
-                       CL_AddQWCTFFlagModel(e, (e->render.effects & EF_FLAG2QW) != 0);
-               }
+       }
+       if (e->render.internaleffects & (INTEF_FLAG1QW | INTEF_FLAG2QW))
+       {
+               // these are only set on player entities
+               CL_AddQWCTFFlagModel(e, (e->render.internaleffects & INTEF_FLAG2QW) != 0);
        }
        // muzzleflash fades over time
        if (e->persistent.muzzleflash > 0)
                e->persistent.muzzleflash -= bound(0, cl.time - cl.oldtime, 0.1) * 20;
-       // LordHavoc: if the model has no flags, don't check each
-       if (e->render.model && e->render.model->flags && (!e->state_current.tagentity && !(e->render.flags & RENDER_VIEWMODEL)))
+       // LordHavoc: if the entity has no effects, don't check each
+       if (e->render.effects && !(e->render.flags & RENDER_VIEWMODEL))
        {
-               if (e->render.model->flags & EF_GIB)
+               if (e->render.effects & EF_GIB)
                        trailtype = EFFECT_TR_BLOOD;
-               else if (e->render.model->flags & EF_ZOMGIB)
+               else if (e->render.effects & EF_ZOMGIB)
                        trailtype = EFFECT_TR_SLIGHTBLOOD;
-               else if (e->render.model->flags & EF_TRACER)
+               else if (e->render.effects & EF_TRACER)
                        trailtype = EFFECT_TR_WIZSPIKE;
-               else if (e->render.model->flags & EF_TRACER2)
+               else if (e->render.effects & EF_TRACER2)
                        trailtype = EFFECT_TR_KNIGHTSPIKE;
-               else if (e->render.model->flags & EF_ROCKET)
+               else if (e->render.effects & EF_ROCKET)
                        trailtype = EFFECT_TR_ROCKET;
-               else if (e->render.model->flags & EF_GRENADE)
+               else if (e->render.effects & EF_GRENADE)
                {
                        // LordHavoc: e->render.alpha == -1 is for Nehahra dem compatibility (cigar smoke)
                        trailtype = e->render.alpha == -1 ? EFFECT_TR_NEHAHRASMOKE : EFFECT_TR_GRENADE;
                }
-               else if (e->render.model->flags & EF_TRACER3)
+               else if (e->render.effects & EF_TRACER3)
                        trailtype = EFFECT_TR_VORESPIKE;
        }
        // do trails
        if (e->render.flags & RENDER_GLOWTRAIL)
                trailtype = EFFECT_TR_GLOWTRAIL;
-       if (trailtype)
+       // check if a trail is allowed (it is not after a teleport for example)
+       if (trailtype && e->persistent.trail_allowed)
        {
                float len;
                vec3_t vel;
@@ -1083,6 +1150,9 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
                VectorScale(vel, len, vel);
                CL_ParticleTrail(trailtype, 1, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor, false, true);
        }
+       // now that the entity has survived one trail update it is allowed to
+       // leave a real trail on later frames
+       e->persistent.trail_allowed = true;
        VectorCopy(origin, e->persistent.trail_origin);
 }
 
@@ -1187,12 +1257,12 @@ void CL_UpdateViewModel(void)
                        ent->state_current.modelindex = 0;
        }
        ent->state_current.alpha = cl.entities[cl.viewentity].state_current.alpha;
-       ent->state_current.effects = EF_NOSHADOW | (cl.entities[cl.viewentity].state_current.effects & (EF_ADDITIVE | EF_REFLECTIVE | EF_FULLBRIGHT | EF_NODEPTHTEST));
+       ent->state_current.effects = EF_NOSHADOW | (cl.entities[cl.viewentity].state_current.effects & (EF_ADDITIVE | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB));
 
        // reset animation interpolation on weaponmodel if model changed
        if (ent->state_previous.modelindex != ent->state_current.modelindex)
        {
-               ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_current.frame;
+               ent->render.frame1 = ent->render.frame2 = ent->state_current.frame;
                ent->render.frame1time = ent->render.frame2time = cl.time;
                ent->render.framelerp = 1;
        }
@@ -1210,12 +1280,7 @@ void CL_LinkNetworkEntity(entity_t *e)
        // skip inactive entities and world
        if (!e->state_current.active || e == cl.entities)
                return;
-       if (e->render.flags & RENDER_VIEWMODEL && !e->state_current.tagentity)
-       {
-               if (!r_drawviewmodel.integer || chase_active.integer || r_refdef.envmap)
-                       return;
-       }
-       else
+       if (e->state_current.tagentity)
        {
                // if the tag entity is currently impossible, skip it
                if (e->state_current.tagentity >= cl.num_entities)
@@ -1298,24 +1363,24 @@ void CL_LinkNetworkEntity(entity_t *e)
                R_RTLight_Update(&r_refdef.lights[r_refdef.numlights++], false, &tempmatrix, color, -1, NULL, true, 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
        }
        // LordHavoc: if the model has no flags, don't check each
-       if (e->render.model && e->render.model->flags && (!e->state_current.tagentity && !(e->render.flags & RENDER_VIEWMODEL)))
+       if (e->render.model && e->render.effects && !(e->render.flags & RENDER_VIEWMODEL))
        {
-               if (e->render.model->flags & EF_GIB)
+               if (e->render.effects & EF_GIB)
                        trailtype = EFFECT_TR_BLOOD;
-               else if (e->render.model->flags & EF_ZOMGIB)
+               else if (e->render.effects & EF_ZOMGIB)
                        trailtype = EFFECT_TR_SLIGHTBLOOD;
-               else if (e->render.model->flags & EF_TRACER)
+               else if (e->render.effects & EF_TRACER)
                        trailtype = EFFECT_TR_WIZSPIKE;
-               else if (e->render.model->flags & EF_TRACER2)
+               else if (e->render.effects & EF_TRACER2)
                        trailtype = EFFECT_TR_KNIGHTSPIKE;
-               else if (e->render.model->flags & EF_ROCKET)
+               else if (e->render.effects & EF_ROCKET)
                        trailtype = EFFECT_TR_ROCKET;
-               else if (e->render.model->flags & EF_GRENADE)
+               else if (e->render.effects & EF_GRENADE)
                {
                        // LordHavoc: e->render.alpha == -1 is for Nehahra dem compatibility (cigar smoke)
                        trailtype = e->render.alpha == -1 ? EFFECT_TR_NEHAHRASMOKE : EFFECT_TR_GRENADE;
                }
-               else if (e->render.model->flags & EF_TRACER3)
+               else if (e->render.effects & EF_TRACER3)
                        trailtype = EFFECT_TR_VORESPIKE;
        }
        // LordHavoc: customizable glow
@@ -1359,6 +1424,10 @@ void CL_LinkNetworkEntity(entity_t *e)
        if (trailtype)
                CL_ParticleTrail(trailtype, 0, origin, origin, vec3_origin, vec3_origin, NULL, e->state_current.glowcolor, true, false);
 
+       // don't show viewmodels in certain situations
+       if (e->render.flags & RENDER_VIEWMODEL)
+               if (!r_drawviewmodel.integer || chase_active.integer || r_refdef.envmap)
+                       return;
        // don't show entities with no modelindex (note: this still shows
        // entities which have a modelindex that resolved to a NULL model)
        if (e->render.model && !(e->render.effects & EF_NODRAW) && r_refdef.numentities < r_refdef.maxentities)
@@ -1474,7 +1543,6 @@ static void CL_RelinkEffects(void)
                                        ent->render.model = cl.model_precache[e->modelindex];
                                else
                                        ent->render.model = cl.csqc_model_precache[-(e->modelindex+1)];
-                               ent->render.frame = ent->render.frame2;
                                ent->render.colormap = -1; // no special coloring
                                ent->render.alpha = 1;
                                VectorSet(ent->render.colormod, 1, 1, 1);
@@ -1526,7 +1594,7 @@ void CL_RelinkBeams(void)
        vec3_t dist, org, start, end;
        float d;
        entity_t *ent;
-       float yaw, pitch;
+       double yaw, pitch;
        float forward;
        matrix4x4_t tempmatrix;
 
@@ -1569,12 +1637,12 @@ void CL_RelinkBeams(void)
                }
                else
                {
-                       yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
+                       yaw = atan2(dist[1], dist[0]) * 180 / M_PI;
                        if (yaw < 0)
                                yaw += 360;
 
                        forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
-                       pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
+                       pitch = atan2(dist[2], forward) * 180 / M_PI;
                        if (pitch < 0)
                                pitch += 360;
                }
@@ -1680,17 +1748,13 @@ void CSQC_RelinkAllEntities (int drawmask)
 
 /*
 ===============
-CL_ReadFromServer
+CL_UpdateWorld
 
-Read all incoming data from the server
+Update client game world for a new frame
 ===============
 */
-int CL_ReadFromServer(void)
+void CL_UpdateWorld(void)
 {
-       CL_ReadDemoMessage();
-       CL_SendMove();
-
-       r_refdef.time = cl.time;
        r_refdef.extraupdate = !r_speeds.integer;
        r_refdef.numentities = 0;
        r_refdef.numlights = 0;
@@ -1733,13 +1797,9 @@ int CL_ReadFromServer(void)
                // move particles
                CL_MoveParticles();
                R_MoveExplosions();
-
-               // update the r_refdef time again because cl.time may have changed in
-               // CL_LerpPoint()
-               r_refdef.time = cl.time;
        }
 
-       return 0;
+       r_refdef.time = cl.time;
 }
 
 // LordHavoc: pausedemo command
@@ -1780,11 +1840,9 @@ For program optimization
 static void CL_TimeRefresh_f (void)
 {
        int i;
-       float timestart, timedelta, oldangles[3];
+       float timestart, timedelta;
 
        r_refdef.extraupdate = false;
-       VectorCopy(cl.viewangles, oldangles);
-       VectorClear(cl.viewangles);
 
        timestart = Sys_DoubleTime();
        for (i = 0;i < 128;i++)
@@ -1794,7 +1852,6 @@ static void CL_TimeRefresh_f (void)
        }
        timedelta = Sys_DoubleTime() - timestart;
 
-       VectorCopy(oldangles, cl.viewangles);
        Con_Printf("%f seconds (%f fps)\n", timedelta, 128/timedelta);
 }
 
@@ -2129,6 +2186,7 @@ CL_Shutdown
 */
 void CL_Shutdown (void)
 {
+       CL_Screen_Shutdown();
        CL_Particles_Shutdown();
        CL_Parse_Shutdown();
 
@@ -2186,6 +2244,11 @@ void CL_Init (void)
        Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "watch a demo file");
        Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "play back a demo as fast as possible and save statistics to benchmark.log");
 
+       // Support Client-side Model Index List
+       Cmd_AddCommand ("cl_modelindexlist", CL_ModelIndexList_f, "list information on all models in the client modelindex");
+       // Support Client-side Sound Index List
+       Cmd_AddCommand ("cl_soundindexlist", CL_SoundIndexList_f, "list all sounds in the client soundindex");
+
        Cvar_RegisterVariable (&cl_autodemo);
        Cvar_RegisterVariable (&cl_autodemo_nameformat);