a big change with a little description...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 26 Apr 2001 05:38:37 +0000 (05:38 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 26 Apr 2001 05:38:37 +0000 (05:38 +0000)
rearranged client entity_t structure
redesigned entity update system (same protocol)
added support for split entity updates in the future for rate capping
glow trails and view relative entities should work now (untested)

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

26 files changed:
bspfile.h
cl_effects.c
cl_input.c
cl_main.c
cl_parse.c
cl_tent.c
client.h
gl_refrag.c
gl_rmain.c
gl_rmisc.c
gl_rsurf.c
mathlib.c
mathlib.h
model_alias.c
pr_cmds.c
protocol.h
quakedef.h
r_light.c
r_part.c
r_sprites.c
render.h
sbar.c
sv_main.c
sv_move.c
transform.c
view.c

index 626c74e..7c8d489 100644 (file)
--- a/bspfile.h
+++ b/bspfile.h
@@ -308,7 +308,7 @@ typedef struct
        epair_t         *epairs;
 } entity_t;
 
-extern int                     num_entities;
+//extern       int                     num_entities;
 extern entity_t        entities[MAX_MAP_ENTITIES];
 
 void   ParseEntities (void);
index 01bea5c..d1973b8 100644 (file)
@@ -118,21 +118,21 @@ void CL_DoEffects()
                        vis = CL_NewTempEntity();
                        if (!vis)
                                continue;
-                       VectorCopy(e->origin, vis->origin);
-                       vis->lerp_model = vis->model = cl.model_precache[e->modelindex];
-                       vis->frame1 = e->frame;
-                       vis->frame2 = e->frame + 1;
-                       if (vis->frame2 >= e->endframe)
-                               vis->frame2 = -1; // disappear
-                       vis->frame = vis->frame2;
-                       vis->framelerp = frame - vis->frame1;
-                       vis->frame1start = e->frame1start;
-                       vis->frame2start = e->frame2start;
-                       vis->lerp_starttime = -1;
-                       vis->colormap = -1; // no special coloring
-                       vis->scale = 1;
-                       vis->alpha = 1;
-                       vis->colormod[0] = vis->colormod[1] = vis->colormod[2] = 1;
+                       VectorCopy(e->origin, vis->render.origin);
+                       vis->render.lerp_model = vis->render.model = cl.model_precache[e->modelindex];
+                       vis->render.frame1 = e->frame;
+                       vis->render.frame2 = e->frame + 1;
+                       if (vis->render.frame2 >= e->endframe)
+                               vis->render.frame2 = -1; // disappear
+                       vis->render.frame = vis->render.frame2;
+                       vis->render.framelerp = frame - vis->render.frame1;
+                       vis->render.frame1start = e->frame1start;
+                       vis->render.frame2start = e->frame2start;
+                       vis->render.lerp_starttime = -1;
+                       vis->render.colormap = -1; // no special coloring
+                       vis->render.scale = 1;
+                       vis->render.alpha = 1;
+                       vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1;
                }
        }
 }
index 21f084f..8906873 100644 (file)
@@ -261,7 +261,7 @@ void CL_AdjustAngles (void)
        {
                cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
                cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
-               cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
+               cl.viewangles[YAW] = ANGLEMOD(cl.viewangles[YAW]);
        }
        if (in_klook.state & 1)
        {
index 40b42eb..e0db84a 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -82,11 +82,11 @@ void CL_ClearState (void)
        // LordHavoc: have to set up the baseline info for alpha and other stuff
        for (i = 0;i < MAX_EDICTS;i++)
        {
-               cl_entities[i].baseline.alpha = 255;
-               cl_entities[i].baseline.scale = 16;
-               cl_entities[i].baseline.glowsize = 0;
-               cl_entities[i].baseline.glowcolor = 254;
-               cl_entities[i].baseline.colormod = 255;
+               cl_entities[i].state_baseline.alpha = 255;
+               cl_entities[i].state_baseline.scale = 16;
+               cl_entities[i].state_baseline.glowsize = 0;
+               cl_entities[i].state_baseline.glowcolor = 254;
+               cl_entities[i].state_baseline.colormod = 255;
        }
 
 //
@@ -267,15 +267,15 @@ void CL_PrintEntities_f (void)
        entity_t        *ent;
        int                     i;
        
-       for (i=0,ent=cl_entities ; i<cl.num_entities ; i++,ent++)
+       for (i = 0, ent = cl_entities;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++)
        {
-               Con_Printf ("%3i:",i);
-               if (!ent->model)
+               Con_Printf ("%3i:", i);
+               if (!ent->render.model)
                {
                        Con_Printf ("EMPTY\n");
                        continue;
                }
-               Con_Printf ("%s:%2i  (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", ent->model->name, ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]);
+               Con_Printf ("%s:%2i  (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", ent->render.model->name, ent->render.frame, ent->render.origin[0], ent->render.origin[1], ent->render.origin[2], ent->render.angles[0], ent->render.angles[1], ent->render.angles[2]);
        }
 }
 
@@ -407,6 +407,26 @@ float      CL_LerpPoint (void)
        return frac;
 }
 
+float CL_EntityLerpPoint (entity_t *ent)
+{
+       float   f;
+
+       if (cl_nolerp.value || cls.timedemo || (sv.active && svs.maxclients == 1))
+               return 1;
+
+       f = ent->state_current.time - ent->state_previous.time;
+//     Con_Printf(" %g-%g=%g", ent->state_current.time, ent->state_previous.time, f);
+
+       if (f <= 0)
+               return 1;
+       if (f >= 0.1)
+               f = 0.1;
+
+//     Con_Printf(" %g-%g/%g=%f", cl.time, ent->state_previous.time, f, (cl.time - ent->state_previous.time) / f);
+       f = (cl.time - ent->state_previous.time) / f;
+       return bound(0, f, 1);
+}
+
 
 /*
 ===============
@@ -421,6 +441,7 @@ void CL_RelinkEntities (void)
        float           frac, f, d;
        vec3_t          delta;
        float           bobjrotate;
+//     float           bobjoffset;
        vec3_t          oldorg;
 
 // determine partial update time       
@@ -431,13 +452,13 @@ void CL_RelinkEntities (void)
 //
 // interpolate player info
 //
-       for (i=0 ; i<3 ; i++)
+       for (i = 0;i < 3;i++)
                cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
 
        if (cls.demoplayback)
        {
        // interpolate the angles       
-               for (j=0 ; j<3 ; j++)
+               for (j = 0;j < 3;j++)
                {
                        d = cl.mviewangles[0][j] - cl.mviewangles[1][j];
                        if (d > 180)
@@ -448,152 +469,180 @@ void CL_RelinkEntities (void)
                }
        }
        
-       bobjrotate = anglemod(100*cl.time);
+       bobjrotate = ANGLEMOD(100*cl.time);
+//     bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f;
        
 // start on the entity after the world
-       for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++)
+       for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++)
        {
-               if (!ent->model)
-               {       // empty slot
-//                     if (ent->forcelink)
-//                             R_RemoveEfrags (ent);   // just became empty
+               // if the object wasn't included in the latest packet, remove it
+               if (!ent->state_current.modelindex)
                        continue;
-               }
-
-// if the object wasn't included in the last packet, remove it
-               if (ent->msgtime != cl.mtime[0])
-               {
-                       ent->model = NULL;
-                       // LordHavoc: free on the same frame, not the next
-//                     if (ent->forcelink)
-//                             R_RemoveEfrags (ent);   // just became empty
-                       continue;
-               }
 
-               VectorCopy (ent->origin, oldorg);
+               VectorCopy (ent->render.origin, oldorg);
 
-               if (ent->forcelink)
-               {       // the entity was not updated in the last message
-                       // so move to the final spot
-                       VectorCopy (ent->msg_origins[0], ent->origin);
-                       VectorCopy (ent->msg_angles[0], ent->angles);
+               if (!ent->state_previous.modelindex)
+               {
+                       // only one state available
+                       VectorCopy (ent->state_current.origin, ent->render.origin);
+                       VectorCopy (ent->state_current.angles, ent->render.angles);
+//                     Con_Printf(" %i", i);
                }
                else
-               {       // if the delta is large, assume a teleport and don't lerp
-                       f = frac;
-                       for (j = 0;j < 3;j++)
+               {
+                       // if the delta is large, assume a teleport and don't lerp
+                       f = CL_EntityLerpPoint(ent);
+                       if (f < 1)
                        {
-                               delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j];
-                               // LordHavoc: increased lerp tolerance from 100 to 200
-                               if (delta[j] > 200 || delta[j] < -200)
-                                       f = 1;          // assume a teleportation, not a motion
+                               for (j = 0;j < 3;j++)
+                               {
+                                       delta[j] = ent->state_current.origin[j] - ent->state_previous.origin[j];
+                                       // LordHavoc: increased lerp tolerance from 100 to 200
+                                       if (delta[j] > 200 || delta[j] < -200)
+                                               f = 1;
+                               }
                        }
-
-               // interpolate the origin and angles
-                       for (j = 0;j < 3;j++)
+                       if (f >= 1)
                        {
-                               ent->origin[j] = ent->msg_origins[1][j] + f*delta[j];
-
-                               d = ent->msg_angles[0][j] - ent->msg_angles[1][j];
-                               if (d > 180)
-                                       d -= 360;
-                               else if (d < -180)
-                                       d += 360;
-                               ent->angles[j] = ent->msg_angles[1][j] + f*d;
+                               // no interpolation
+                               VectorCopy (ent->state_current.origin, ent->render.origin);
+                               VectorCopy (ent->state_current.angles, ent->render.angles);
+                       }
+                       else
+                       {
+                               // interpolate the origin and angles
+                               for (j = 0;j < 3;j++)
+                               {
+                                       ent->render.origin[j] = ent->state_previous.origin[j] + f*delta[j];
+
+                                       d = ent->state_current.angles[j] - ent->state_previous.angles[j];
+                                       if (d > 180)
+                                               d -= 360;
+                                       else if (d < -180)
+                                               d += 360;
+                                       ent->render.angles[j] = ent->state_previous.angles[j] + f*d;
+                               }
                        }
-                       
                }
 
-               if (ent->effects & EF_BRIGHTFIELD)
-                       R_EntityParticles (ent);
-               if (ent->effects & EF_MUZZLEFLASH)
+               ent->render.flags = ent->state_current.flags;
+               ent->render.effects = ent->state_current.effects;
+               ent->render.model = cl.model_precache[ent->state_current.modelindex];
+               ent->render.frame = ent->state_current.frame;
+               if (cl.scores == NULL || !ent->state_current.colormap)
+                       ent->render.colormap = -1; // no special coloring
+               else
+                       ent->render.colormap = cl.scores[ent->state_current.colormap - 1].colors; // color it
+               ent->render.skinnum = ent->state_current.skin;
+               ent->render.alpha = ent->state_current.alpha * (1.0f / 255.0f); // FIXME: interpolate?
+               ent->render.scale = ent->state_current.scale * (1.0f / 16.0f); // FIXME: interpolate?
+               ent->render.glowsize = ent->state_current.glowsize * 4.0f; // FIXME: interpolate?
+               ent->render.glowcolor = ent->state_current.glowcolor;
+               ent->render.colormod[0] = (float) ((ent->state_current.colormod >> 5) & 7) * (1.0f / 7.0f);
+               ent->render.colormod[1] = (float) ((ent->state_current.colormod >> 2) & 7) * (1.0f / 7.0f);
+               ent->render.colormod[2] = (float) (ent->state_current.colormod & 3) * (1.0f / 3.0f);
+
+               // LordHavoc: if the entity has no effects, don't check each
+               if (ent->render.effects)
                {
-                       vec3_t v;
+                       if (ent->render.effects & EF_BRIGHTFIELD)
+                               R_EntityParticles (ent);
+                       if (ent->render.effects & EF_MUZZLEFLASH)
+                       {
+                               vec3_t v;
 
-                       AngleVectors (ent->angles, v, NULL, NULL);
+                               AngleVectors (ent->render.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;
+                               v[0] = v[0] * 18 + ent->render.origin[0];
+                               v[1] = v[1] * 18 + ent->render.origin[1];
+                               v[2] = v[2] * 18 + ent->render.origin[2] + 16;
 
-                       CL_AllocDlight (ent, v, 100, 1, 1, 1, 0, 0.1);
-               }
-               if (ent->effects & EF_BRIGHTLIGHT)
-                       CL_AllocDlight (ent, ent->origin, 400, 1, 1, 1, 0, 0);
-               if (ent->effects & EF_DIMLIGHT)
-                       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
-                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.2f, 1.0f, 0, 0);
-                       else // red
-                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.1f, 0.1f, 0, 0);
-               }
-               else if (ent->effects & EF_BLUE) // blue
-                       CL_AllocDlight (ent, ent->origin, 200, 0.1f, 0.1f, 1.0f, 0, 0);
-               else if (ent->effects & EF_FLAME)
-               {
-                       if (ent->model)
+                               CL_AllocDlight (ent, v, 100, 1, 1, 1, 0, 0.1);
+                       }
+                       if (ent->render.effects & EF_BRIGHTLIGHT)
+                               CL_AllocDlight (ent, ent->render.origin, 400, 1, 1, 1, 0, 0);
+                       if (ent->render.effects & EF_DIMLIGHT)
+                               CL_AllocDlight (ent, ent->render.origin, 200, 1, 1, 1, 0, 0);
+                       // LordHavoc: added EF_RED and EF_BLUE
+                       if (ent->render.effects & EF_RED) // red
+                       {                       
+                               if (ent->render.effects & EF_BLUE) // magenta
+                                       CL_AllocDlight (ent, ent->render.origin, 200, 1.0f, 0.2f, 1.0f, 0, 0);
+                               else // red
+                                       CL_AllocDlight (ent, ent->render.origin, 200, 1.0f, 0.1f, 0.1f, 0, 0);
+                       }
+                       else if (ent->render.effects & EF_BLUE) // blue
+                               CL_AllocDlight (ent, ent->render.origin, 200, 0.1f, 0.1f, 1.0f, 0, 0);
+                       else if (ent->render.effects & EF_FLAME)
                        {
-                               vec3_t mins, maxs;
-                               int temp;
-                               VectorAdd(ent->origin, ent->model->mins, mins);
-                               VectorAdd(ent->origin, ent->model->maxs, maxs);
-                               // how many flames to make
-                               temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300);
-                               R_FlameCube(mins, maxs, temp);
+                               if (ent->render.model)
+                               {
+                                       vec3_t mins, maxs;
+                                       int temp;
+                                       VectorAdd(ent->render.origin, ent->render.model->mins, mins);
+                                       VectorAdd(ent->render.origin, ent->render.model->maxs, maxs);
+                                       // how many flames to make
+                                       temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300);
+                                       R_FlameCube(mins, maxs, temp);
+                               }
+                               CL_AllocDlight (ent, ent->render.origin, lhrandom(200, 250), 1.0f, 0.7f, 0.3f, 0, 0);
                        }
-                       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
+               // LordHavoc: if the model has no flags, don't check each
+               if (ent->render.model && ent->render.model->flags)
                {
-               // rotate binary objects locally
-                       if (ent->model->flags & EF_ROTATE)
-                               ent->angles[1] = bobjrotate;
-                       if (ent->model->flags & EF_GIB)
-                               R_RocketTrail (oldorg, ent->origin, 2, ent);
-                       else if (ent->model->flags & EF_ZOMGIB)
-                               R_RocketTrail (oldorg, ent->origin, 4, ent);
-                       else if (ent->model->flags & EF_TRACER)
-                               R_RocketTrail (oldorg, ent->origin, 3, ent);
-                       else if (ent->model->flags & EF_TRACER2)
-                               R_RocketTrail (oldorg, ent->origin, 5, ent);
-                       else if (ent->model->flags & EF_ROCKET)
+                       if (ent->render.model->flags & EF_ROTATE)
                        {
-                               R_RocketTrail (oldorg, ent->origin, 0, ent);
-                               CL_AllocDlight (ent, ent->origin, 200, 1.0f, 0.8f, 0.4f, 0, 0);
+                               ent->render.angles[1] = bobjrotate;
+//                             ent->render.origin[2] += bobjoffset;
                        }
-                       else if (ent->model->flags & EF_GRENADE)
+                       // only do trails if present in the previous frame as well
+                       if (ent->state_previous.modelindex)
                        {
-                               if (ent->alpha == -1) // LordHavoc: Nehahra dem compatibility
-                                       R_RocketTrail (oldorg, ent->origin, 7, ent);
-                               else
-                                       R_RocketTrail (oldorg, ent->origin, 1, ent);
+                               if (ent->render.model->flags & EF_GIB)
+                                       R_RocketTrail (oldorg, ent->render.origin, 2, ent);
+                               else if (ent->render.model->flags & EF_ZOMGIB)
+                                       R_RocketTrail (oldorg, ent->render.origin, 4, ent);
+                               else if (ent->render.model->flags & EF_TRACER)
+                                       R_RocketTrail (oldorg, ent->render.origin, 3, ent);
+                               else if (ent->render.model->flags & EF_TRACER2)
+                                       R_RocketTrail (oldorg, ent->render.origin, 5, ent);
+                               else if (ent->render.model->flags & EF_ROCKET)
+                               {
+                                       R_RocketTrail (oldorg, ent->render.origin, 0, ent);
+                                       CL_AllocDlight (ent, ent->render.origin, 200, 1.0f, 0.8f, 0.4f, 0, 0);
+                               }
+                               else if (ent->render.model->flags & EF_GRENADE)
+                               {
+                                       if (ent->render.alpha == -1) // LordHavoc: Nehahra dem compatibility
+                                               R_RocketTrail (oldorg, ent->render.origin, 7, ent);
+                                       else
+                                               R_RocketTrail (oldorg, ent->render.origin, 1, ent);
+                               }
+                               else if (ent->render.model->flags & EF_TRACER3)
+                                       R_RocketTrail (oldorg, ent->render.origin, 6, ent);
                        }
-                       else if (ent->model->flags & EF_TRACER3)
-                               R_RocketTrail (oldorg, ent->origin, 6, ent);
                }
-               if (ent->glowsize) // LordHavoc: customizable glow
+               if (ent->render.glowsize) // LordHavoc: customizable glow
                {
-                       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);
+                       byte *tempcolor = (byte *)&d_8to24table[ent->render.glowcolor];
+                       CL_AllocDlight (ent, ent->render.origin, ent->render.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);
-
-               ent->forcelink = false;
+               if (ent->render.flags & RENDER_GLOWTRAIL) // LordHavoc: customizable glow and trail
+                       R_RocketTrail2 (oldorg, ent->render.origin, ent->render.glowcolor, ent);
 
                if (i == cl.viewentity && !chase_active.value)
                        continue;
 
-// LordHavoc: enabled EF_NODRAW
-               if (!ent->model || ent->effects & EF_NODRAW)
+               if (ent->render.model == NULL)
+                       continue;
+               if (ent->render.effects & EF_NODRAW)
                        continue;
                if (cl_numvisedicts < MAX_VISEDICTS)
                        cl_visedicts[cl_numvisedicts++] = ent;
        }
+//     Con_Printf("\n");
 }
 
 
index d856ce1..942e2b3 100644 (file)
@@ -100,16 +100,21 @@ This error checks and tracks the total number of entities
 */
 entity_t       *CL_EntityNum (int num)
 {
+       /*
        if (num >= cl.num_entities)
        {
                if (num >= MAX_EDICTS)
                        Host_Error ("CL_EntityNum: %i is an invalid number",num);
-               while (cl.num_entities<=num)
-               {
-                       cl_entities[cl.num_entities].colormap = -1; // no special coloring
-                       cl.num_entities++;
-               }
+               cl.num_entities = num;
+//             while (cl.num_entities <= num)
+//             {
+//                     cl_entities[cl.num_entities].colormap = -1; // no special coloring
+//                     cl.num_entities++;
+//             }
        }
+       */
+       if (num >= MAX_EDICTS)
+               Host_Error ("CL_EntityNum: %i is an invalid number",num);
                
        return &cl_entities[num];
 }
@@ -441,7 +446,7 @@ void CL_ParseServerInfo (void)
 
 
 // local state
-       cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
+       cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
        
        R_NewMap ();
 
@@ -450,6 +455,24 @@ void CL_ParseServerInfo (void)
        noclip_anglehack = false;               // noclip is turned off at start        
 }
 
+void CL_ValidateState(entity_state_t *s)
+{
+       model_t *model;
+
+       if (s->modelindex >= MAX_MODELS)
+               Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
+
+       // colormap is client index + 1
+       if (s->colormap > cl.maxclients)
+               Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
+
+       model = cl.model_precache[s->modelindex];
+       if (model && s->frame >= model->numframes)
+       {
+               Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
+               s->frame = 0;
+       }
+}
 
 /*
 ==================
@@ -460,13 +483,11 @@ If an entities model or origin changes from frame to frame, it must be
 relinked.  Other attributes can change without relinking.
 ==================
 */
+byte entkill[MAX_EDICTS];
 void CL_ParseUpdate (int bits)
 {
-       int                     i, modnum, num, alpha, scale, glowsize, glowcolor, colormod, frame;
-       model_t         *model;
-       qboolean        forcelink;
-       entity_t        *ent;
-       entity_state_t *baseline;
+       int num, deltadie;
+       entity_t *ent;
 
        if (cls.signon == SIGNONS - 1)
        {       // first update is the final signon stage
@@ -476,7 +497,7 @@ void CL_ParseUpdate (int bits)
 
        if (bits & U_MOREBITS)
                bits |= (MSG_ReadByte()<<8);
-       if (bits & U_EXTEND1 && !Nehahrademcompatibility)
+       if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
        {
                bits |= MSG_ReadByte() << 16;
                if (bits & U_EXTEND2)
@@ -484,141 +505,125 @@ void CL_ParseUpdate (int bits)
        }
 
        if (bits & U_LONGENTITY)        
-               num = MSG_ReadShort ();
+               num = (unsigned) MSG_ReadShort ();
        else
-               num = MSG_ReadByte ();
+               num = (unsigned) MSG_ReadByte ();
 
-       ent = CL_EntityNum (num);
+       if (num >= MAX_EDICTS)
+               Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
+       if (num < 1)
+               Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
 
-       forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from
+       // mark as visible (no kill)
+       entkill[num] = 0;
 
-       ent->msgtime = cl.mtime[0];
-       
-       // LordHavoc: new protocol stuff
-       baseline = &ent->baseline;
-       if (bits & U_DELTA)
-               baseline = &ent->deltabaseline;
+       ent = CL_EntityNum (num);
 
-       if (forcelink)
+       ent->state_previous = ent->state_current;
+       deltadie = false;
+       if (bits & U_DELTA)
        {
-               ent->deltabaseline.origin[0] = ent->deltabaseline.origin[1] = ent->deltabaseline.origin[2] = 0;
-               ent->deltabaseline.angles[0] = ent->deltabaseline.angles[1] = ent->deltabaseline.angles[2] = 0;
-               ent->deltabaseline.effects = 0;
-               ent->deltabaseline.modelindex = 0;
-               ent->deltabaseline.frame = 0;
-               ent->deltabaseline.colormap = 0;
-               ent->deltabaseline.skin = 0;
-               ent->deltabaseline.alpha = 255;
-               ent->deltabaseline.scale = 16;
-               ent->deltabaseline.glowsize = 0;
-               ent->deltabaseline.glowcolor = 254;
-               ent->deltabaseline.colormod = 255;
+               if (!ent->state_current.modelindex)
+                       deltadie = true; // was not present in previous frame, leave hidden until next full update
        }
-
-       modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex;
-       if (modnum >= MAX_MODELS)
-               Host_Error ("CL_ParseModel: bad modnum");
-
-       frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
-
-       i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
-       ent->deltabaseline.colormap = i;
-       if (!i)
-               ent->colormap = -1; // no special coloring
        else
+               ent->state_current = ent->state_baseline;
+
+       ent->state_current.time = cl.mtime[0];
+
+       ent->state_current.flags = 0;
+       if (bits & U_MODEL)             ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
+       if (bits & U_FRAME)             ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
+       if (bits & U_COLORMAP)  ent->state_current.colormap = MSG_ReadByte();
+       if (bits & U_SKIN)              ent->state_current.skin = MSG_ReadByte();
+       if (bits & U_EFFECTS)   ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
+       if (bits & U_ORIGIN1)   ent->state_current.origin[0] = MSG_ReadCoord();
+       if (bits & U_ANGLE1)    ent->state_current.angles[0] = MSG_ReadAngle();
+       if (bits & U_ORIGIN2)   ent->state_current.origin[1] = MSG_ReadCoord();
+       if (bits & U_ANGLE2)    ent->state_current.angles[1] = MSG_ReadAngle();
+       if (bits & U_ORIGIN3)   ent->state_current.origin[2] = MSG_ReadCoord();
+       if (bits & U_ANGLE3)    ent->state_current.angles[2] = MSG_ReadAngle();
+       if (bits & U_STEP)              ent->state_current.flags |= RENDER_STEP;
+       if (bits & U_ALPHA)             ent->state_current.alpha = MSG_ReadByte();
+       if (bits & U_SCALE)             ent->state_current.scale = MSG_ReadByte();
+       if (bits & U_EFFECTS2)  ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
+       if (bits & U_GLOWSIZE)  ent->state_current.glowsize = MSG_ReadByte();
+       if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
+       if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
+       if (bits & U_COLORMOD)  ent->state_current.colormod = MSG_ReadByte();
+       if (bits & U_FRAME2)    ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
+       if (bits & U_MODEL2)    ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
+       if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
+
+       // LordHavoc: to allow playback of the Nehahra movie
+       if (Nehahrademcompatibility && (bits & U_EXTEND1))
        {
-               if (i > cl.maxclients)
-                       Host_Error ("i >= cl.maxclients");
-               ent->colormap = cl.scores[i-1].colors; // color it
-       }
-
-       ent->deltabaseline.skin = ent->skinnum = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
-
-       ent->effects = ((bits & U_EFFECTS) ? MSG_ReadByte() : (baseline->effects & 0xFF));
-
-// shift the known values for interpolation
-       VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
-       VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
-       VectorCopy (baseline->origin, ent->msg_origins[0]);
-       VectorCopy (baseline->angles, ent->msg_angles[0]);
-
-       if (bits & U_ORIGIN1) ent->msg_origins[0][0] = MSG_ReadCoord ();
-       if (bits & U_ANGLE1) ent->msg_angles[0][0] = MSG_ReadAngle();
-       if (bits & U_ORIGIN2) ent->msg_origins[0][1] = MSG_ReadCoord ();
-       if (bits & U_ANGLE2) ent->msg_angles[0][1] = MSG_ReadAngle();
-       if (bits & U_ORIGIN3) ent->msg_origins[0][2] = MSG_ReadCoord ();
-       if (bits & U_ANGLE3) ent->msg_angles[0][2] = MSG_ReadAngle();
-
-       VectorCopy(ent->msg_origins[0], ent->deltabaseline.origin);
-       VectorCopy(ent->msg_angles[0], ent->deltabaseline.angles);
-
-       alpha = bits & U_ALPHA ? MSG_ReadByte() : baseline->alpha;
-       scale = bits & U_SCALE ? MSG_ReadByte() : baseline->scale;
-       ent->effects |= ((bits & U_EFFECTS2) ? (MSG_ReadByte() << 8) : (baseline->effects & 0xFF00));
-       glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize;
-       glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor;
-       colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod;
-       modnum |= ((bits & U_MODEL2) ? (MSG_ReadByte() << 8) : (baseline->modelindex & 0xFF00));
-       frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
-
-       if (modnum >= MAX_MODELS)
-               Host_Error("modnum (%i) >= MAX_MODELS (%i)\n", modnum, MAX_MODELS);
-
-       model = cl.model_precache[modnum];
-       if (model != ent->model)
-       {
-               ent->model = model;
-       // automatic animation (torches, etc) can be either all together
-       // or randomized
-               if (model)
-                       ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
+               // LordHavoc: evil format
+               int i = MSG_ReadFloat();
+               int j = MSG_ReadFloat() * 255.0f;
+               if (i == 2)
+               {
+                       if (MSG_ReadFloat())
+                               ent->state_current.effects |= EF_FULLBRIGHT;
+               }
+               if (j < 0)
+                       ent->state_current.alpha = 0;
+               else if (j == 0 || j >= 255)
+                       ent->state_current.alpha = 255;
                else
-                       forcelink = true;       // hack to make null model players work
+                       ent->state_current.alpha = j;
        }
 
-       ent->frame = frame;
-       if (model && (unsigned) frame >= model->numframes)
-               Con_DPrintf("CL_ParseUpdate: no such frame %i in \"%s\"\n", frame, model->name);
-
-       ent->deltabaseline.alpha = alpha;
-       ent->deltabaseline.scale = scale;
-       ent->deltabaseline.effects = ent->effects;
-       ent->deltabaseline.glowsize = glowsize;
-       ent->deltabaseline.glowcolor = glowcolor;
-       ent->deltabaseline.colormod = colormod;
-       ent->deltabaseline.modelindex = modnum;
-       ent->deltabaseline.frame = frame;
-       ent->alpha = (float) alpha * (1.0 / 255.0);
-       ent->scale = (float) scale * (1.0 / 16.0);
-       ent->glowsize = glowsize * 4.0;
-       ent->glowcolor = glowcolor;
-       ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0);
-       ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0);
-       ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0);
-       if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the Nehahra movie
+       if (deltadie)
        {
-               i = MSG_ReadFloat();
-               ent->alpha = MSG_ReadFloat();
-               if (i == 2 && MSG_ReadFloat() != 0.0)
-                       ent->effects |= EF_FULLBRIGHT;
-               if (ent->alpha == 0)
-                       ent->alpha = 1;
+               // hide the entity
+               ent->state_current.modelindex = 0;
        }
+       else
+       {
+               CL_ValidateState(&ent->state_current);
 
-       //if ( bits & U_NOLERP )
-       //      ent->forcelink = true;
-       //if (bits & U_STEP) // FIXME: implement clientside interpolation of monsters
-
-       if ( forcelink )
-       {       // didn't have an update last message
-               VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
-               VectorCopy (ent->msg_origins[0], ent->origin);
-               VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
-               VectorCopy (ent->msg_angles[0], ent->angles);
-               ent->forcelink = true;
+               /*
+               if (!ent->state_current.modelindex)
+               {
+                       if (bits & U_DELTA)
+                       {
+                               if (bits & U_MODEL)
+                                       Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
+                               else
+                                       Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
+                       }
+                       else
+                       {
+                               if (bits & U_MODEL)
+                                       Con_Printf("CL_ParseUpdate:       NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
+                               else
+                                       Con_Printf("CL_ParseUpdate:       NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
+                       }
+               }
+               */
        }
 }
 
+int entityupdatestart;
+void CL_EntityUpdateBegin(int start)
+{
+       if (start < 0 || start >= MAX_EDICTS)
+               Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
+       entityupdatestart = start;
+       memset(entkill, 1, MAX_EDICTS);
+}
+
+void CL_EntityUpdateEnd(int end)
+{
+       int i;
+       if (end < 0 || end > MAX_EDICTS)
+               Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
+       for (i = entityupdatestart;i < end;i++)
+               if (entkill[i])
+                       cl_entities[i].state_current.modelindex = 0;
+}
+
 /*
 ==================
 CL_ParseBaseline
@@ -626,28 +631,29 @@ CL_ParseBaseline
 */
 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
 {
-       int                     i;
+       int i;
 
+       memset(&ent->state_baseline, 0, sizeof(entity_state_t));
        if (largemodelindex)
-               ent->baseline.modelindex = (unsigned short) MSG_ReadShort ();
+               ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
        else
-               ent->baseline.modelindex = MSG_ReadByte ();
-       ent->baseline.frame = MSG_ReadByte ();
-       ent->baseline.colormap = MSG_ReadByte();
-       ent->baseline.skin = MSG_ReadByte();
-       for (i=0 ; i<3 ; i++)
+               ent->state_baseline.modelindex = MSG_ReadByte ();
+       ent->state_baseline.frame = MSG_ReadByte ();
+       ent->state_baseline.colormap = MSG_ReadByte();
+       ent->state_baseline.skin = MSG_ReadByte();
+       for (i = 0;i < 3;i++)
        {
-               ent->baseline.origin[i] = MSG_ReadCoord ();
-               ent->baseline.angles[i] = MSG_ReadAngle ();
+               ent->state_baseline.origin[i] = MSG_ReadCoord ();
+               ent->state_baseline.angles[i] = MSG_ReadAngle ();
        }
-       ent->baseline.alpha = 255;
-       ent->baseline.scale = 16;
-       ent->baseline.glowsize = 0;
-       ent->baseline.glowcolor = 254;
-       ent->baseline.colormod = 255;
-       
-       if (ent->baseline.modelindex >= MAX_MODELS)
-               Host_Error("CL_ParseBaseline: modelindex (%i) >= MAX_MODELS (%i)\n", ent->baseline.modelindex, MAX_MODELS);
+       ent->state_baseline.alpha = 255;
+       ent->state_baseline.scale = 16;
+       ent->state_baseline.glowsize = 0;
+       ent->state_baseline.glowcolor = 254;
+       ent->state_baseline.colormod = 255;
+       ent->state_previous = ent->state_current = ent->state_baseline;
+
+       CL_ValidateState(&ent->state_baseline);
 }
 
 
@@ -660,7 +666,7 @@ Server information pertaining to this client only
 */
 void CL_ParseClientdata (int bits)
 {
-       int             i, j;
+       int i, j;
 
        bits &= 0xFFFF;
        if (bits & SU_EXTEND1)
@@ -739,34 +745,31 @@ CL_ParseStatic
 void CL_ParseStatic (int largemodelindex)
 {
        entity_t *ent;
-       int             i;
                
-       i = cl.num_statics;
-       if (i >= MAX_STATIC_ENTITIES)
+       if (cl.num_statics >= MAX_STATIC_ENTITIES)
                Host_Error ("Too many static entities");
-       ent = &cl_static_entities[i];
-       cl.num_statics++;
+       ent = &cl_static_entities[cl.num_statics++];
        CL_ParseBaseline (ent, largemodelindex);
 
 // copy it to the current state
-       ent->model = cl.model_precache[ent->baseline.modelindex];
-       ent->frame = ent->frame1 = ent->frame2 = ent->baseline.frame;
-       ent->framelerp = 0;
-       ent->lerp_starttime = -1;
+       ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
+       ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
+       ent->render.framelerp = 0;
+       ent->render.lerp_starttime = -1;
        // make torchs play out of sync
-       ent->frame1start = ent->frame2start = -(rand() & 32767);
-       ent->colormap = -1; // no special coloring
-       ent->skinnum = ent->baseline.skin;
-       ent->effects = ent->baseline.effects;
-       ent->alpha = 1;
-       ent->scale = 1;
-       ent->alpha = 1;
-       ent->glowsize = 0;
-       ent->glowcolor = 254;
-       ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
-
-       VectorCopy (ent->baseline.origin, ent->origin);
-       VectorCopy (ent->baseline.angles, ent->angles); 
+       ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
+       ent->render.colormap = -1; // no special coloring
+       ent->render.skinnum = ent->state_baseline.skin;
+       ent->render.effects = ent->state_baseline.effects;
+       ent->render.alpha = 1;
+       ent->render.scale = 1;
+       ent->render.alpha = 1;
+       ent->render.glowsize = 0;
+       ent->render.glowcolor = 254;
+       ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
+
+       VectorCopy (ent->state_baseline.origin, ent->render.origin);
+       VectorCopy (ent->state_baseline.angles, ent->render.angles);    
        R_AddEfrags (ent);
 }
 
@@ -832,7 +835,7 @@ CL_ParseServerMessage
 void CL_ParseServerMessage (void)
 {
        int                     cmd;
-       int                     i;
+       int                     i, updateend;
        byte            cmdlog[32];
        char            *cmdlogname[32], *temp;
        int                     cmdindex, cmdcount = 0;
@@ -856,6 +859,8 @@ void CL_ParseServerMessage (void)
 // parse the message
 //
        MSG_BeginReading ();
+
+       updateend = false;
        
        while (1)
        {
@@ -867,7 +872,7 @@ void CL_ParseServerMessage (void)
                if (cmd == -1)
                {
                        SHOWNET("END OF MESSAGE");
-                       return;         // end of message
+                       break;          // end of message
                }
 
                cmdindex = cmdcount & 31;
@@ -878,7 +883,7 @@ void CL_ParseServerMessage (void)
                if (cmd & 128)
                {
                        // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
-                       temp = "svc_entity";
+                       temp = "entity";
                        cmdlogname[cmdindex] = temp;
                        SHOWNET("fast update");
                        CL_ParseUpdate (cmd&127);
@@ -926,6 +931,9 @@ void CL_ParseServerMessage (void)
                        break;
                        
                case svc_time:
+                       // handle old protocols which do not have entity update ranges
+                       CL_EntityUpdateBegin(0);
+                       updateend = true;
                        cl.mtime[1] = cl.mtime[0];
                        cl.mtime[0] = MSG_ReadFloat ();                 
                        break;
@@ -938,10 +946,7 @@ void CL_ParseServerMessage (void)
                case svc_version:
                        i = MSG_ReadLong ();
                        if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
-                       {
                                Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
-                               return;
-                       }
                        Nehahrademcompatibility = false;
                        if (i == 250)
                                Nehahrademcompatibility = true;
@@ -986,7 +991,7 @@ void CL_ParseServerMessage (void)
                case svc_lightstyle:
                        i = MSG_ReadByte ();
                        if (i >= MAX_LIGHTSTYLES)
-                               Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
+                               Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
                        strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
                        cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
                        cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
@@ -1131,7 +1136,19 @@ void CL_ParseServerMessage (void)
                case svc_showlmp:
                        SHOWLMP_decodeshow();
                        break;
+               case svc_entitiesbegin:
+                       // the beginning of an entity update range
+                       CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
+                       break;
+               case svc_entitiesend:
+                       // the end of an entity update range
+                       CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
+                       updateend = false;
+                       break;
                }
        }
+
+       if (updateend)
+               CL_EntityUpdateEnd(MAX_EDICTS);
 }
 
index 363ca59..22b258b 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -443,10 +443,10 @@ entity_t *CL_NewTempEntity (void)
        memset (ent, 0, sizeof(*ent));
        cl_visedicts[cl_numvisedicts++] = ent;
 
-       ent->colormap = -1; // no special coloring
-       ent->scale = 1;
-       ent->alpha = 1;
-       ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
+       ent->render.colormap = -1; // no special coloring
+       ent->render.scale = 1;
+       ent->render.alpha = 1;
+       ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
        return ent;
 }
 
@@ -474,13 +474,11 @@ void CL_UpdateTEnts (void)
                if (!b->model || b->endtime < cl.time)
                        continue;
 
-       // if coming from the player, update the start position
+               // if coming from the player, update the start position
                if (b->entity == cl.viewentity)
-               {
-                       VectorCopy (cl_entities[cl.viewentity].origin, b->start);
-               }
+                       VectorCopy (cl_entities[cl.viewentity].render.origin, b->start);
 
-       // calculate pitch and yaw
+               // calculate pitch and yaw
                VectorSubtract (b->end, b->start, dist);
 
                if (dist[1] == 0 && dist[0] == 0)
@@ -503,7 +501,7 @@ void CL_UpdateTEnts (void)
                                pitch += 360;
                }
 
-       // add new entities for the lightning
+               // add new entities for the lightning
                VectorCopy (b->start, org);
                d = VectorNormalizeLength(dist);
                while (d > 0)
@@ -511,15 +509,15 @@ void CL_UpdateTEnts (void)
                        ent = CL_NewTempEntity ();
                        if (!ent)
                                return;
-                       VectorCopy (org, ent->origin);
-                       ent->model = b->model;
-                       ent->effects = EF_FULLBRIGHT;
-                       ent->angles[0] = pitch;
-                       ent->angles[1] = yaw;
-                       ent->angles[2] = rand()%360;
+                       VectorCopy (org, ent->render.origin);
+                       ent->render.model = b->model;
+                       ent->render.effects = EF_FULLBRIGHT;
+                       ent->render.angles[0] = pitch;
+                       ent->render.angles[1] = yaw;
+                       ent->render.angles[2] = rand()%360;
 
                        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);
+                               CL_AllocDlight(ent, ent->render.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 f7aa2af..42845cd 100644 (file)
--- a/client.h
+++ b/client.h
@@ -144,7 +144,7 @@ typedef struct
 // information for local display
        int                     stats[MAX_CL_STATS];    // health, etc
        int                     items;                  // inventory bit flags
-       float   item_gettime[32];       // cl.time of aquiring item, for blinking
+       float           item_gettime[32];       // cl.time of acquiring item, for blinking
        float           faceanimtime;   // use anim frame if cl.time < this
 
        cshift_t        cshifts[NUM_CSHIFTS];   // color shifts for damage, powerups
@@ -208,7 +208,7 @@ typedef struct
 // refresh related state
        struct model_s  *worldmodel;    // cl_entitites[0].model
        struct efrag_s  *free_efrags;
-       int                     num_entities;   // held in cl_entities array
+//     int                     num_entities;   // held in cl_entities array
        int                     num_statics;    // held in cl_staticentities array
        entity_t        viewent;                        // the gun model
 
index 224899f..ce5ba79 100644 (file)
@@ -52,7 +52,7 @@ void R_RemoveEfrags (entity_t *ent)
 {
        efrag_t         *ef, *old, *walk, **prev;
        
-       ef = ent->efrag;
+       ef = ent->render.efrag;
        
        while (ef)
        {
@@ -79,7 +79,7 @@ void R_RemoveEfrags (entity_t *ent)
                cl.free_efrags = old;
        }
        
-       ent->efrag = NULL; 
+       ent->render.efrag = NULL; 
 }
 
 /*
@@ -181,25 +181,25 @@ void R_AddEfrags (entity_t *ent)
        model_t         *entmodel;
        int                     i;
                
-       if (!ent->model)
+       if (!ent->render.model)
                return;
 
        r_addent = ent;
                        
-       lastlink = &ent->efrag;
+       lastlink = &ent->render.efrag;
        r_pefragtopnode = NULL;
        
-       entmodel = ent->model;
+       entmodel = ent->render.model;
 
        for (i=0 ; i<3 ; i++)
        {
-               r_emins[i] = ent->origin[i] + entmodel->mins[i];
-               r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
+               r_emins[i] = ent->render.origin[i] + entmodel->mins[i];
+               r_emaxs[i] = ent->render.origin[i] + entmodel->maxs[i];
        }
 
        R_SplitEntityOnNode (cl.worldmodel->nodes);
 
-       ent->topnode = r_pefragtopnode;
+       ent->render.topnode = r_pefragtopnode;
 }
 
 
@@ -220,7 +220,7 @@ void R_StoreEfrags (efrag_t **ppefrag)
        while ((pefrag = *ppefrag) != NULL)
        {
                pent = pefrag->entity;
-               clmodel = pent->model;
+               clmodel = pent->render.model;
 
                switch (clmodel->type)
                {
@@ -229,10 +229,10 @@ void R_StoreEfrags (efrag_t **ppefrag)
                case mod_sprite:
                        pent = pefrag->entity;
 
-                       if ((pent->visframe != r_framecount) && (cl_numvisedicts < MAX_VISEDICTS))
+                       if ((pent->render.visframe != r_framecount) && (cl_numvisedicts < MAX_VISEDICTS))
                        {
                                cl_visedicts[cl_numvisedicts++] = pent;
-                               pent->visframe = r_framecount; // render each entity only once per frame
+                               pent->render.visframe = r_framecount; // render each entity only once per frame
                        }
 
                        ppefrag = &pefrag->leafnext;
index f3806a3..d266859 100644 (file)
@@ -344,45 +344,70 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
 void R_LerpUpdate(entity_t *ent)
 {
        int frame;
-       frame = ent->frame;
-       if (ent->model && ent->frame >= ent->model->numframes)
+       frame = ent->render.frame;
+       if (ent->render.model && ent->render.frame >= ent->render.model->numframes)
        {
-               Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->frame, ent->model->name);
+               Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->render.frame, ent->render.model->name);
                frame = 0;
        }
 
-       if (ent->lerp_model != ent->model)
+       if (ent->render.lerp_model != ent->render.model)
        {
                // reset all interpolation information
-               ent->lerp_model = ent->model;
-               ent->frame1 = ent->frame2 = frame;
-               ent->frame1start = ent->frame2start = cl.time;
-               ent->framelerp = 1;
-               ent->lerp_starttime = 0;
+               ent->render.lerp_model = ent->render.model;
+               ent->render.frame1 = ent->render.frame2 = frame;
+               ent->render.frame1start = ent->render.frame2start = cl.time;
+               ent->render.framelerp = 1;
+               ent->render.lerp_starttime = 0;
        }
-       else if (ent->frame2 != frame)
+       else if (ent->render.frame2 != frame)
        {
                // transition to new frame
-               ent->frame1 = ent->frame2;
-               ent->frame1start = ent->frame2start;
-               ent->frame2 = frame;
-               ent->frame2start = cl.time;
-               ent->framelerp = 0;
-               ent->lerp_starttime = cl.time;
+               ent->render.frame1 = ent->render.frame2;
+               ent->render.frame1start = ent->render.frame2start;
+               ent->render.frame2 = frame;
+               ent->render.frame2start = cl.time;
+               ent->render.framelerp = 0;
+               ent->render.lerp_starttime = cl.time;
        }
        else
        {
                // lerp_starttime < 0 is used to prevent changing of framelerp
-               if (ent->lerp_starttime >= 0)
+               if (ent->render.lerp_starttime >= 0)
                {
                        // update transition
-                       ent->framelerp = (cl.time - ent->lerp_starttime) * 10;
-                       ent->framelerp = bound(0, ent->framelerp, 1);
+                       ent->render.framelerp = (cl.time - ent->render.lerp_starttime) * 10;
+                       ent->render.framelerp = bound(0, ent->render.framelerp, 1);
                }
        }
 }
 
 
+void R_PrepareEntities (void)
+{
+       int i;
+       entity_t *ent;
+       vec3_t v;
+       // this updates entities that are supposed to be view relative
+       for (i = 0;i < cl_numvisedicts;i++)
+       {
+               ent = cl_visedicts[i];
+
+               if (ent->render.flags & RENDER_VIEWMODEL)
+               {
+                       // remove flag so it will not be repeated incase RelinkEntities is not called again for a while
+                       ent->render.flags -= RENDER_VIEWMODEL;
+                       // transform origin
+                       VectorCopy(ent->render.origin, v);
+                       ent->render.origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_refdef.vieworg[0];
+                       ent->render.origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_refdef.vieworg[1];
+                       ent->render.origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_refdef.vieworg[2];
+                       // adjust angles
+                       VectorAdd(ent->render.angles, r_refdef.viewangles, ent->render.angles);
+               }
+       }
+}
+
 /*
 =============
 R_DrawEntitiesOnList
@@ -396,12 +421,12 @@ void R_DrawEntitiesOnList1 (void)
        if (!r_drawentities.value)
                return;
 
-       for (i=0 ; i<cl_numvisedicts ; i++)
+       for (i = 0;i < cl_numvisedicts;i++)
        {
-               if (cl_visedicts[i]->model->type != mod_brush)
+               if (cl_visedicts[i]->render.model->type != mod_brush)
                        continue;
                currententity = cl_visedicts[i];
-               modelalpha = currententity->alpha;
+               modelalpha = currententity->render.alpha;
 
                R_DrawBrushModel (currententity);
        }
@@ -415,25 +440,22 @@ void R_DrawEntitiesOnList2 (void)
        if (!r_drawentities.value)
                return;
 
-       for (i=0 ; i<cl_numvisedicts ; i++)
+       for (i = 0;i < cl_numvisedicts;i++)
        {
                currententity = cl_visedicts[i];
-               modelalpha = currententity->alpha;
+               modelalpha = currententity->render.alpha;
 
-               switch (currententity->model->type)
+               switch (currententity->render.model->type)
                {
                case mod_alias:
-                       if (!strcmp(currententity->model->name, "progs/flame2.mdl"))
-                               blend[0].frame = 0;
-
                        R_LerpUpdate(currententity);
-                       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
-                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap);
+                       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
+                       R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
                        break;
 
                case mod_sprite:
                        R_LerpUpdate(currententity);
-                       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
+                       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
                        R_DrawSpriteModel (currententity, blend);
                        break;
 
@@ -452,21 +474,21 @@ void R_DrawViewModel (void)
 {
        frameblend_t blend[4];
 
-       if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.model)
+       if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
                return;
 
        currententity = &cl.viewent;
-       currententity->alpha = modelalpha = cl_entities[cl.viewentity].alpha; // LordHavoc: if the player is transparent, so is his gun
-       currententity->effects = cl_entities[cl.viewentity].effects;
-       currententity->scale = 1;
-       VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod);
+       currententity->render.alpha = modelalpha = cl_entities[cl.viewentity].render.alpha; // LordHavoc: if the player is transparent, so is the gun
+       currententity->render.effects = cl_entities[cl.viewentity].render.effects;
+       currententity->render.scale = 1;
+       VectorCopy(cl_entities[cl.viewentity].render.colormod, currententity->render.colormod);
 
        R_LerpUpdate(currententity);
-       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
+       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
 
        // hack the depth range to prevent view model from poking into walls
        glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
-       R_DrawAliasModel (currententity, false, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap);
+       R_DrawAliasModel (currententity, false, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
        glDepthRange (gldepthmin, gldepthmax);
 }
 
@@ -773,8 +795,8 @@ void R_RenderView (void)
 //     if (r_norefresh.value)
 //             return;
 
-       if (!r_worldentity.model || !cl.worldmodel)
-               Sys_Error ("R_RenderView: NULL worldmodel");
+       if (!r_worldentity.render.model || !cl.worldmodel)
+               Host_Error ("R_RenderView: NULL worldmodel");
 
        lighthalf = gl_lightmode.value;
 
@@ -796,6 +818,8 @@ void R_RenderView (void)
        R_SetFrustum ();
        R_SetupGL ();
 
+       R_PrepareEntities();
+
        skypolyclear();
        wallpolyclear();
        transpolyclear();
index 72dc5e4..cfc884d 100644 (file)
@@ -170,7 +170,7 @@ void R_NewMap (void)
                d_lightstylevalue[i] = 264;             // normal light value
 
        memset (&r_worldentity, 0, sizeof(r_worldentity));
-       r_worldentity.model = cl.worldmodel;
+       r_worldentity.render.model = cl.worldmodel;
        currententity = &r_worldentity;
 
 // clear out efrags in case the level hasn't been reloaded
index 9031969..3db2230 100644 (file)
@@ -121,7 +121,7 @@ int R_AddDynamicLights (msurface_t *surf)
                if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
                        continue;                                       // not lit by this light
 
-               VectorSubtract (cl_dlights[lnum].origin, currententity->origin, local);
+               VectorSubtract (cl_dlights[lnum].origin, currententity->render.origin, local);
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
@@ -280,7 +280,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
        lightmap = surf->samples;
 
 // set to full bright if no light data
-       if ((currententity && (currententity->effects & EF_FULLBRIGHT)) || !cl.worldmodel->lightdata)
+       if ((currententity && (currententity->render.effects & EF_FULLBRIGHT)) || !cl.worldmodel->lightdata)
        {
                bl = blocklights;
                for (i=0 ; i<size ; i++)
@@ -374,7 +374,7 @@ texture_t *R_TextureAnimation (texture_t *base)
        int             relative;
        int             count;
 
-       if (currententity->frame)
+       if (currententity->render.frame)
        {
                if (base->alternate_anims)
                        base = base->alternate_anims;
@@ -819,14 +819,14 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
        if (s->dlightframe == r_dlightframecount)
                RSurf_Light(s->dlightbits, s->polys);
        wv = wvert;
-       if (isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1))
+       if (isbmodel && (currententity->render.colormod[0] != 1 || currententity->render.colormod[1] != 1 || currententity->render.colormod[2] != 1))
        {
                for (p = s->polys;p;p = p->next)
                {
                        v = p->verts[0];
-                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
                        for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
-                               transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->colormod[0], wv[4] * currententity->colormod[1], wv[5] * currententity->colormod[2], alpha);
+                               transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->render.colormod[0], wv[4] * currententity->render.colormod[1], wv[5] * currententity->render.colormod[2], alpha);
                        transpolyend();
                }
        }
@@ -835,7 +835,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
                for (p = s->polys;p;p = p->next)
                {
                        v = p->verts[0];
-                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
                        for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
                                transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha);
                        transpolyend();
@@ -932,22 +932,22 @@ void R_DrawBrushModel (entity_t *e)
 
        currententity = e;
 
-       clmodel = e->model;
+       clmodel = e->render.model;
 
-       if (e->angles[0] || e->angles[1] || e->angles[2])
+       if (e->render.angles[0] || e->render.angles[1] || e->render.angles[2])
        {
                rotated = true;
                for (i=0 ; i<3 ; i++)
                {
-                       mins[i] = e->origin[i] - clmodel->radius;
-                       maxs[i] = e->origin[i] + clmodel->radius;
+                       mins[i] = e->render.origin[i] - clmodel->radius;
+                       maxs[i] = e->render.origin[i] + clmodel->radius;
                }
        }
        else
        {
                rotated = false;
-               VectorAdd (e->origin, clmodel->mins, mins);
-               VectorAdd (e->origin, clmodel->maxs, maxs);
+               VectorAdd (e->render.origin, clmodel->mins, mins);
+               VectorAdd (e->render.origin, clmodel->maxs, maxs);
        }
 
        if (R_CullBox (mins, maxs))
@@ -955,14 +955,14 @@ void R_DrawBrushModel (entity_t *e)
 
        c_bmodels++;
 
-       VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
+       VectorSubtract (r_refdef.vieworg, e->render.origin, modelorg);
        if (rotated)
        {
                vec3_t  temp;
                vec3_t  forward, right, up;
 
                VectorCopy (modelorg, temp);
-               AngleVectors (e->angles, forward, right, up);
+               AngleVectors (e->render.angles, forward, right, up);
                modelorg[0] = DotProduct (temp, forward);
                modelorg[1] = -DotProduct (temp, right);
                modelorg[2] = DotProduct (temp, up);
@@ -977,14 +977,14 @@ void R_DrawBrushModel (entity_t *e)
                if (!cl_dlights[i].radius)
                        continue;
 
-               VectorSubtract(cl_dlights[i].origin, currententity->origin, org);
+               VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org);
                R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel);
        }
-       vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->effects & EF_FULLBRIGHT) || currententity->colormod[0] != 1 || currententity->colormod[2] != 1 || currententity->colormod[2] != 1;
+       vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1;
 
-e->angles[0] = -e->angles[0];  // stupid quake bug
+e->render.angles[0] = -e->render.angles[0];    // stupid quake bug
        softwaretransformforentity (e);
-e->angles[0] = -e->angles[0];  // stupid quake bug
+e->render.angles[0] = -e->render.angles[0];    // stupid quake bug
 
        // draw texture
        for (i = 0;i < clmodel->nummodelsurfaces;i++, s++)
@@ -1298,10 +1298,10 @@ void R_DrawWorld (void)
        entity_t        ent;
 
        memset (&ent, 0, sizeof(ent));
-       ent.model = cl.worldmodel;
-       ent.colormod[0] = ent.colormod[1] = ent.colormod[2] = 1;
-       modelalpha = ent.alpha = 1;
-       ent.scale = 1;
+       ent.render.model = cl.worldmodel;
+       ent.render.colormod[0] = ent.render.colormod[1] = ent.render.colormod[2] = 1;
+       modelalpha = ent.render.alpha = 1;
+       ent.render.scale = 1;
 
        VectorCopy (r_refdef.vieworg, modelorg);
 
index 9d847ad..a1e7939 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -29,8 +29,6 @@ int nanmask = 255<<23;
 
 /*-----------------------------------------------------------------*/
 
-#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
-
 float m_bytenormals[NUMVERTEXNORMALS][3] =
 {
 {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188}, 
@@ -465,18 +463,6 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
 /*-----------------------------------------------------------------*/
 
 
-float  anglemod(float a)
-{
-#if 0
-       if (a >= 0)
-               a -= 360*(int)(a/360);
-       else
-               a += 360*( 1 + (int)(-a/360) );
-#endif
-       a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
-       return a;
-}
-
 // LordHavoc note 1:
 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
 // assembly in an attempt to accelerate it further, very inefficient
index fde3d3e..4b613ba 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -36,6 +36,10 @@ typedef      int     fixed16_t;
 #define M_PI           3.14159265358979323846  // matches value in gcc v2 math.h
 #endif
 
+#define DEG2RAD(a) ((a) * ((float) M_PI / 180.0f))
+#define RAD2DEG(a) ((a) * (180.0f / (float) M_PI))
+#define ANGLEMOD(a) (((int) ((a) * (65536.0f / 360.0f)) & 65535) * (360.0f / 65536.0f))
+
 struct mplane_s;
 
 extern vec3_t vec3_origin;
@@ -90,7 +94,6 @@ void FloorDivMod (double numer, double denom, int *quotient, int *rem);
 int GreatestCommonDivisor (int i1, int i2);
 
 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
-float  anglemod(float a);
 
 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up);
index f29d3a9..9e1c035 100644 (file)
@@ -36,12 +36,11 @@ int                 posenum;
 
 float          aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations
 
-#define MAXVERTS 8192
-float vertst[MAXVERTS][2];
-int vertusage[MAXVERTS];
-int vertonseam[MAXVERTS];
-int vertremap[MAXVERTS];
-unsigned short temptris[MAXVERTS][3];
+float vertst[MAXALIASVERTS][2];
+int vertusage[MAXALIASVERTS];
+int vertonseam[MAXALIASVERTS];
+int vertremap[MAXALIASVERTS];
+unsigned short temptris[MAXALIASTRIS][3];
 
 void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
 {
@@ -85,7 +84,7 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert
                }
        }
        if (invalidnormals)
-               Con_Printf("Mod_ConvertAliasVerts: %i invalid normal indices found\n", invalidnormals);
+               Con_Printf("Mod_ConvertAliasVerts: \"%s\", %i invalid normal indices found\n", loadname, invalidnormals);
 }
 
 /*
@@ -532,7 +531,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        numverts = LittleLong(pinmodel->numverts);
        BOUNDI(numverts,0,MAXALIASVERTS);
        numtris = LittleLong(pinmodel->numtris);
-       BOUNDI(numtris,0,65536);
+       BOUNDI(numtris,0,MAXALIASTRIS);
        numskins = LittleLong(pinmodel->numskins);
        BOUNDI(numskins,0,256);
        skinwidth = LittleLong (pinmodel->skinwidth);
@@ -722,7 +721,7 @@ void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, triv
                }
        }
        if (invalidnormals)
-               Con_Printf("Mod_ConvertQ2AliasVerts: %i invalid normal indices found\n", invalidnormals);
+               Con_Printf("Mod_ConvertQ2AliasVerts: \"%s\", %i invalid normal indices found\n", loadname, invalidnormals);
 }
 
 /*
index e4ba51a..4d312c7 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -1619,7 +1619,7 @@ void PF_changeyaw (void)
        float           ideal, current, move, speed;
        
        ent = PROG_TO_EDICT(pr_global_struct->self);
-       current = anglemod( ent->v.angles[1] );
+       current = ANGLEMOD(ent->v.angles[1]);
        ideal = ent->v.ideal_yaw;
        speed = ent->v.yaw_speed;
        
@@ -1647,7 +1647,7 @@ void PF_changeyaw (void)
                        move = -speed;
        }
        
-       ent->v.angles[1] = anglemod (current + move);
+       ent->v.angles[1] = ANGLEMOD (current + move);
 }
 
 /*
@@ -1662,7 +1662,7 @@ void PF_changepitch (void)
        eval_t          *val;
        
        ent = G_EDICT(OFS_PARM0);
-       current = anglemod( ent->v.angles[0] );
+       current = ANGLEMOD( ent->v.angles[0] );
        if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
                ideal = val->_float;
        else
@@ -1702,7 +1702,7 @@ void PF_changepitch (void)
                        move = -speed;
        }
        
-       ent->v.angles[0] = anglemod (current + move);
+       ent->v.angles[0] = ANGLEMOD (current + move);
 }
 
 /*
index edad508..b7cf55c 100644 (file)
@@ -46,6 +46,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define EF_FULLBRIGHT                  512             // LordHavoc: fullbright
 #define EF_FLAME                               1024    // LordHavoc: on fire
 
+#define EF_STEP                                        0x80000000 // internal client use only - present on MOVETYPE_STEP entities, not QC accessible (too many bits)
+
 // if the high bit of the servercmd is set, the low bits are fast update flags:
 #define        U_MOREBITS      (1<<0)
 #define        U_ORIGIN1       (1<<1)
@@ -206,6 +208,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define        svc_sound2                      54              // short soundindex instead of byte
 #define        svc_spawnbaseline2      55              // short modelindex instead of byte
 #define svc_spawnstatic2       56              // short modelindex instead of byte
+#define svc_entitiesbegin      57              // [short] entitynum
+#define svc_entitiesend                58              // [short] entitynum
 
 //
 // client to server
index db706ec..7b67999 100644 (file)
@@ -187,24 +187,6 @@ extern int buildnumber;
 #include "zone.h"
 #include "mathlib.h"
 
-// LordHavoc: made this more compact, and added some more fields
-typedef struct
-{
-       vec3_t  origin;
-       vec3_t  angles;
-       int             effects;
-       short   modelindex;
-       short   frame;
-       byte    colormap;
-       byte    skin;
-       byte    alpha;
-       byte    scale;
-       byte    glowsize;
-       byte    glowcolor;
-       byte    colormod;
-} entity_state_t;
-
-
 #include "r_textures.h"
 
 #include "wad.h"
index 37a2a0f..2c4d2d0 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -817,17 +817,17 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
        a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
        if (lighthalf)
        {
-               mod[0] = ent->colormod[0] * 0.5f;
-               mod[1] = ent->colormod[1] * 0.5f;
-               mod[2] = ent->colormod[2] * 0.5f;
+               mod[0] = ent->render.colormod[0] * 0.5f;
+               mod[1] = ent->render.colormod[1] * 0.5f;
+               mod[2] = ent->render.colormod[2] * 0.5f;
        }
        else
        {
-               mod[0] = ent->colormod[0];
-               mod[1] = ent->colormod[1];
-               mod[2] = ent->colormod[2];
+               mod[0] = ent->render.colormod[0];
+               mod[1] = ent->render.colormod[1];
+               mod[2] = ent->render.colormod[2];
        }
-       if (ent->effects & EF_FULLBRIGHT)
+       if (ent->render.effects & EF_FULLBRIGHT)
        {
                ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
                ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
index 2e3f8f3..ed53ba2 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -65,6 +65,7 @@ rtexture_t *smokeparticletexture[8];
 rtexture_t *rainparticletexture;
 rtexture_t *bubbleparticletexture;
 rtexture_t *bulletholetexture[8];
+rtexture_t *rocketglowparticletexture;
 
 particle_t     *particles;
 int                    r_numparticles;
@@ -245,6 +246,21 @@ void R_InitParticleTexture (void)
 
                bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        }
+
+       for (y = 0;y < 32;y++)
+       {
+               dy = y - 16;
+               for (x = 0;x < 32;x++)
+               {
+                       dx = x - 16;
+                       d = (2048.0f / (dx*dx+dy*dy+1)) - 8.0f;
+                       data[y][x][0] = bound(0, d * 1.0f, 255);
+                       data[y][x][1] = bound(0, d * 0.8f, 255);
+                       data[y][x][2] = bound(0, d * 0.5f, 255);
+                       data[y][x][3] = bound(0, d * 1.0f, 255);
+               }
+       }
+       rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
 void r_part_start()
@@ -444,7 +460,7 @@ void R_EntityParticles (entity_t *ent)
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               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);
+               particle(pt_oneframe, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
        }
 }
 
@@ -837,12 +853,10 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        VectorSubtract(end, start, dir);
        VectorNormalize(dir);
 
-       /*
        if (type == 0) // rocket glow
-               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);
-       */
+               particle(pt_oneframe, 254, rocketglowparticletexture, TPOLYTYPE_ADD, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0);
 
-       t = ent->trail_time;
+       t = ent->render.trail_time;
        if (t >= cl.time)
                return; // no particles to spawn this frame (sparse trail)
 
@@ -854,7 +868,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        if (len <= 0.01f)
        {
                // advance the trail time
-               ent->trail_time = cl.time;
+               ent->render.trail_time = cl.time;
                return;
        }
        speed = len / (cl.time - cl.oldtime);
@@ -869,14 +883,14 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
        {
                // advance the trail time
-               ent->trail_time = cl.time;
+               ent->render.trail_time = cl.time;
                return;
        }
 
        bubbles = (contents == CONTENTS_WATER || contents == CONTENTS_SLIME);
 
        polytype = TPOLYTYPE_ALPHA;
-       if (ent->effects & EF_ADDITIVE)
+       if (ent->render.effects & EF_ADDITIVE)
                polytype = TPOLYTYPE_ADD;
 
        while (t < cl.time)
@@ -974,7 +988,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                dec *= speed;
                VectorMA (start, dec, vec, start);
        }
-       ent->trail_time = t;
+       ent->render.trail_time = t;
 }
 
 void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
index db8e90e..95facc3 100644 (file)
@@ -4,7 +4,7 @@ void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t
 {
        byte alphaub;
        alphaub = bound(0, alpha, 255);
-       transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+       transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
        transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub);
        transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub);
        transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
@@ -29,34 +29,34 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
 
        c_sprites++;
 
-       psprite = Mod_Extradata(e->model);
+       psprite = Mod_Extradata(e->render.model);
        //psprite = e->model->cache.data;
 
        if (psprite->type == SPR_ORIENTED)
        {       // bullet marks on walls
-               AngleVectors (e->angles, NULL, right, up);
-               VectorSubtract(e->origin, vpn, org);
+               AngleVectors (e->render.angles, NULL, right, up);
+               VectorSubtract(e->render.origin, vpn, org);
        }
        else
        {       // normal sprite
                VectorCopy(vup, up);
                VectorCopy(vright, right);
-               VectorCopy(e->origin, org);
+               VectorCopy(e->render.origin, org);
        }
-       if (e->scale != 1)
+       if (e->render.scale != 1)
        {
-               VectorScale(up, e->scale, up);
-               VectorScale(right, e->scale, right);
+               VectorScale(up, e->render.scale, up);
+               VectorScale(right, e->render.scale, right);
        }
 
-       if (e->model->flags & EF_FULLBRIGHT || e->effects & EF_FULLBRIGHT)
+       if (e->render.model->flags & EF_FULLBRIGHT || e->render.effects & EF_FULLBRIGHT)
        {
-               color[0] = e->colormod[0] * 255;
-               color[1] = e->colormod[1] * 255;
-               color[2] = e->colormod[2] * 255;
+               color[0] = e->render.colormod[0] * 255;
+               color[1] = e->render.colormod[1] * 255;
+               color[2] = e->render.colormod[2] * 255;
        }
        else
-               R_CompleteLightPoint(color, e->origin, true);
+               R_CompleteLightPoint(color, e->render.origin, true);
 
        colorub[0] = bound(0, color[0], 255);
        colorub[1] = bound(0, color[1], 255);
@@ -64,12 +64,12 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
 
        // LordHavoc: interpolated sprite rendering
        if (blend[0].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->alpha*255*blend[0].lerp);
+               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[0].lerp);
        if (blend[1].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[1].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->alpha*255*blend[1].lerp);
+               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[1].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[1].lerp);
        if (blend[2].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[2].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->alpha*255*blend[2].lerp);
+               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[2].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[2].lerp);
        if (blend[3].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[3].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->alpha*255*blend[3].lerp);
+               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[3].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[3].lerp);
 }
 
index e69a5bd..d67134d 100644 (file)
--- a/render.h
+++ b/render.h
@@ -35,57 +35,77 @@ typedef struct efrag_s
        struct efrag_s          *entnext;
 } efrag_t;
 
+#define RENDER_STEP 1
+#define RENDER_GLOWTRAIL 2
+#define RENDER_VIEWMODEL 4
+
+// LordHavoc: made this more compact, and added some more fields
+typedef struct
+{
+       double  time; // time this state was updated
+       vec3_t  origin;
+       vec3_t  angles;
+       int             effects;
+       unsigned short modelindex;
+       unsigned short frame;
+       byte    colormap;
+       byte    skin;
+       byte    alpha;
+       byte    scale;
+       byte    glowsize;
+       byte    glowcolor;
+       byte    colormod;
+       byte    flags;
+} entity_state_t;
 
 typedef struct entity_s
 {
-       qboolean                                forcelink;              // model changed
-
-       int                                             update_type;
-
-       entity_state_t                  baseline;               // to fill in defaults in updates
-       entity_state_t                  deltabaseline;  // LordHavoc: previous frame
-
-       double                                  msgtime;                // time of last update
-       vec3_t                                  msg_origins[2]; // last two updates (0 is newest)       
-       vec3_t                                  origin;
-       vec3_t                                  msg_angles[2];  // last two updates (0 is newest)
-       vec3_t                                  angles; 
-
-       // LordHavoc: added support for alpha transprency and other effects
-       float                                   alpha;                  // opacity (alpha) of the model
-       float                                   colormod[3];    // color tint for model
-       float                                   scale;                  // size the model is shown
-       float                                   trail_time;
-       float                                   glowsize;               // how big the glow is
-       byte                                    glowcolor;              // color of glow and particle trail (paletted)
-       byte                                    glowtrail;              // leaves a trail of particles
-       byte                                    isviewmodel;    // attached to view
-
-       struct model_s                  *model;                 // NULL = no model
-       struct efrag_s                  *efrag;                 // linked list of efrags
-       int                                             frame;                  // current desired frame (usually identical to frame2, but frame2 is not always used)
-       struct model_s                  *lerp_model;    // lerp resets when model changes
-       float                                   lerp_starttime; // start of this transition
-       int                                             frame1;                 // frame that the model is interpolating from
-       int                                             frame2;                 // frame that the model is interpolating to
-       double                                  framelerp;              // interpolation factor, usually computed from lerp_starttime
-       double                                  frame1start;    // time frame1 began playing (for framegroup animations)
-       double                                  frame2start;    // time frame2 began playing (for framegroup animations)
-       float                                   syncbase;               // for client-side animations
-       int                                             colormap;
-       int                                             effects;                // light, particles, etc
-       int                                             skinnum;                // for Alias models
-       int                                             visframe;               // last frame this entity was
-                                                                                       //  found in an active leaf
-                                                                                       
-       int                                             dlightframe;    // dynamic lighting
-       int                                             dlightbits[8];
-       
-// FIXME: could turn these into a union
-       int                                             trivial_accept;
-       struct mnode_s                  *topnode;               // for bmodels, first world node
-                                                                                       //  that splits bmodel, or NULL if
-                                                                                       //  not split
+       entity_state_t                  state_baseline; // baseline for entity
+       entity_state_t                  state_previous; // previous state (interpolating from this)
+       entity_state_t                  state_current;  // current state (interpolating to this)
+
+       struct
+       {
+               vec3_t                                  origin;
+               vec3_t                                  angles; 
+
+               // LordHavoc: added support for alpha transprency and other effects
+               float                                   alpha;                  // opacity (alpha) of the model
+               float                                   colormod[3];    // color tint for model
+               float                                   scale;                  // size the model is shown
+               float                                   glowsize;               // how big the glow is
+               byte                                    glowcolor;              // color of glow and particle trail (paletted)
+               byte                                    flags;                  // render flags
+
+               struct model_s                  *model;                 // NULL = no model
+               int                                             frame;                  // current desired frame (usually identical to frame2, but frame2 is not always used)
+               struct efrag_s                  *efrag;                 // linked list of efrags
+               int                                             colormap;
+               int                                             effects;                // light, particles, etc
+               int                                             skinnum;                // for Alias models
+
+               int                                             visframe;               // last frame this entity was found in an active leaf
+
+               struct model_s                  *lerp_model;    // lerp resets when model changes
+               float                                   lerp_starttime; // start of this transition
+               int                                             frame1;                 // frame that the model is interpolating from
+               int                                             frame2;                 // frame that the model is interpolating to
+               double                                  framelerp;              // interpolation factor, usually computed from lerp_starttime
+               double                                  frame1start;    // time frame1 began playing (for framegroup animations)
+               double                                  frame2start;    // time frame2 began playing (for framegroup animations)
+//             float                                   syncbase;               // for client-side animations
+
+               int                                             dlightframe;    // dynamic lighting
+               int                                             dlightbits[8];
+               
+               float                                   trail_time;
+       // FIXME: could turn these into a union
+//             int                                             trivial_accept;
+               struct mnode_s                  *topnode;               // for bmodels, first world node
+                                                                                               //  that splits bmodel, or NULL if
+                                                                                               //  not split
+       }
+       render;
 } entity_t;
 
 // !!! if this is changed, it must be changed in asm_draw.h too !!!
diff --git a/sbar.c b/sbar.c
index fd63c13..32e1db6 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -783,6 +783,9 @@ void Sbar_DrawFace (void)
                f = 4;
        else
                f = cl.stats[STAT_HEALTH] / 20;
+       // LordHavoc: I don't even know how the game didn't crash without this
+       if (f < 0)
+               f = 0;
 
        if (cl.time <= cl.faceanimtime)
        {
index 330a9ba..59da2be 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -483,6 +483,8 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                MSG_WriteFloat(msg, org[2]);
        }
        */
+       MSG_WriteByte(msg, svc_entitiesbegin);
+       MSG_WriteShort(msg, 1);
 
        clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
 // send over all entities (except the client) that touch the pvs
@@ -744,6 +746,9 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                if (bits & U_FRAME2)    MSG_WriteByte(msg, (int)ent->v.frame >> 8);
                if (bits & U_MODEL2)    MSG_WriteByte(msg, (int)ent->v.modelindex >> 8);
        }
+
+       MSG_WriteByte(msg, svc_entitiesend);
+       MSG_WriteShort(msg, MAX_EDICTS);
 }
 
 /*
index 87f3ed4..8bf64f6 100644 (file)
--- a/sv_move.c
+++ b/sv_move.c
@@ -287,8 +287,8 @@ void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
        float                   d[3];
        float           tdir, olddir, turnaround;
 
-       olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
-       turnaround = anglemod(olddir - 180);
+       olddir = ANGLEMOD((int)(actor->v.ideal_yaw/45)*45);
+       turnaround = ANGLEMOD(olddir - 180);
 
        deltax = enemy->v.origin[0] - actor->v.origin[0];
        deltay = enemy->v.origin[1] - actor->v.origin[1];
index e025c7f..52107ef 100644 (file)
@@ -151,8 +151,8 @@ void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale)
 void softwaretransformforentity (entity_t *e)
 {
        vec3_t angles;
-       angles[0] = -e->angles[0];
-       angles[1] = e->angles[1];
-       angles[2] = e->angles[2];
-       softwaretransformset(e->origin, angles, e->scale);
+       angles[0] = -e->render.angles[0];
+       angles[1] = e->render.angles[1];
+       angles[2] = e->render.angles[2];
+       softwaretransformset(e->render.origin, angles, e->render.scale);
 }
diff --git a/view.c b/view.c
index 5eddbe6..793fec6 100644 (file)
--- a/view.c
+++ b/view.c
@@ -312,10 +312,10 @@ void V_ParseDamage (void)
 //
        ent = &cl_entities[cl.viewentity];
        
-       VectorSubtract (from, ent->origin, from);
+       VectorSubtract (from, ent->render.origin, from);
        VectorNormalize (from);
        
-       AngleVectors (ent->angles, forward, right, NULL);
+       AngleVectors (ent->render.angles, forward, right, NULL);
 
        side = DotProduct (from, right);
        v_dmg_roll = count*side*v_kickroll.value;
@@ -555,7 +555,7 @@ void V_UpdateBlends (void)
 
 float angledelta (float a)
 {
-       a = anglemod(a);
+       a = ANGLEMOD(a);
        if (a > 180)
                a -= 360;
        return a;
@@ -615,12 +615,12 @@ void CalcGunAngle (void)
        cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
        cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
        */
-       cl.viewent.angles[YAW] = r_refdef.viewangles[YAW];
-       cl.viewent.angles[PITCH] = -r_refdef.viewangles[PITCH];
+       cl.viewent.render.angles[YAW] = r_refdef.viewangles[YAW];
+       cl.viewent.render.angles[PITCH] = -r_refdef.viewangles[PITCH];
 
-       cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
-       cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
-       cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+       cl.viewent.render.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
+       cl.viewent.render.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
+       cl.viewent.render.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
 }
 
 /*
@@ -634,21 +634,21 @@ void V_BoundOffsets (void)
        
        ent = &cl_entities[cl.viewentity];
 
-// absolutely bound refresh reletive to entity clipping hull
+// absolutely bound refresh relative to entity clipping hull
 // so the view can never be inside a solid wall
 
-       if (r_refdef.vieworg[0] < ent->origin[0] - 14)
-               r_refdef.vieworg[0] = ent->origin[0] - 14;
-       else if (r_refdef.vieworg[0] > ent->origin[0] + 14)
-               r_refdef.vieworg[0] = ent->origin[0] + 14;
-       if (r_refdef.vieworg[1] < ent->origin[1] - 14)
-               r_refdef.vieworg[1] = ent->origin[1] - 14;
-       else if (r_refdef.vieworg[1] > ent->origin[1] + 14)
-               r_refdef.vieworg[1] = ent->origin[1] + 14;
-       if (r_refdef.vieworg[2] < ent->origin[2] - 22)
-               r_refdef.vieworg[2] = ent->origin[2] - 22;
-       else if (r_refdef.vieworg[2] > ent->origin[2] + 30)
-               r_refdef.vieworg[2] = ent->origin[2] + 30;
+       if (r_refdef.vieworg[0] < ent->render.origin[0] - 14)
+               r_refdef.vieworg[0] = ent->render.origin[0] - 14;
+       else if (r_refdef.vieworg[0] > ent->render.origin[0] + 14)
+               r_refdef.vieworg[0] = ent->render.origin[0] + 14;
+       if (r_refdef.vieworg[1] < ent->render.origin[1] - 14)
+               r_refdef.vieworg[1] = ent->render.origin[1] - 14;
+       else if (r_refdef.vieworg[1] > ent->render.origin[1] + 14)
+               r_refdef.vieworg[1] = ent->render.origin[1] + 14;
+       if (r_refdef.vieworg[2] < ent->render.origin[2] - 22)
+               r_refdef.vieworg[2] = ent->render.origin[2] - 22;
+       else if (r_refdef.vieworg[2] > ent->render.origin[2] + 30)
+               r_refdef.vieworg[2] = ent->render.origin[2] + 30;
 }
 
 /*
@@ -677,7 +677,7 @@ void V_CalcViewRoll (void)
 {
        float           side;
                
-       side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity);
+       side = V_CalcRoll (cl_entities[cl.viewentity].render.angles, cl.velocity);
        r_refdef.viewangles[ROLL] += side;
 
        if (v_dmg_time > 0)
@@ -712,9 +712,9 @@ void V_CalcIntermissionRefdef (void)
 // view is the weapon model (only visible from inside body)
        view = &cl.viewent;
 
-       VectorCopy (ent->origin, r_refdef.vieworg);
-       VectorCopy (ent->angles, r_refdef.viewangles);
-       view->model = NULL;
+       VectorCopy (ent->render.origin, r_refdef.vieworg);
+       VectorCopy (ent->render.angles, r_refdef.viewangles);
+       view->render.model = NULL;
 
 // always idle in intermission
        old = v_idlescale.value;
@@ -747,67 +747,64 @@ void V_CalcRefdef (void)
        view = &cl.viewent;
        
 
-// transform the view offset by the model's matrix to get the offset from
-// model origin for the view
+// transform the view offset by the model's matrix to get the offset from model origin for the view
        if (!chase_active.value) // LordHavoc: get rid of angle problems in chase_active mode
        {
-               ent->angles[YAW] = cl.viewangles[YAW];  // the model should face the view dir
-               ent->angles[PITCH] = -cl.viewangles[PITCH];     // the model should face the view dir
+               ent->render.angles[YAW] = cl.viewangles[YAW];   // the model should face the view dir
+               ent->render.angles[PITCH] = -cl.viewangles[PITCH];      // the model should face the view dir
        }
                                                                                
        
        bob = V_CalcBob ();
        
 // refresh position
-       VectorCopy (ent->origin, r_refdef.vieworg);
+       VectorCopy (ent->render.origin, r_refdef.vieworg);
        r_refdef.vieworg[2] += cl.viewheight + bob;
 
+       // LordHavoc: the protocol has changed...  so this is an obsolete approach
 // never let it sit exactly on a node line, because a water plane can
 // dissapear when viewed with the eye exactly on it.
 // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
-       r_refdef.vieworg[0] += 1.0/32;
-       r_refdef.vieworg[1] += 1.0/32;
-       r_refdef.vieworg[2] += 1.0/32;
+//     r_refdef.vieworg[0] += 1.0/32;
+//     r_refdef.vieworg[1] += 1.0/32;
+//     r_refdef.vieworg[2] += 1.0/32;
 
        if (!intimerefresh)
-       {
                VectorCopy (cl.viewangles, r_refdef.viewangles);
-       }
        V_CalcViewRoll ();
        V_AddIdle ();
 
 // offsets
-       angles[PITCH] = -ent->angles[PITCH];    // because entity pitches are
-                                                                                       //  actually backward
-       angles[YAW] = ent->angles[YAW];
-       angles[ROLL] = ent->angles[ROLL];
+       angles[PITCH] = -ent->render.angles[PITCH];     // because entity pitches are actually backward
+       angles[YAW] = ent->render.angles[YAW];
+       angles[ROLL] = ent->render.angles[ROLL];
 
        AngleVectors (angles, forward, NULL, NULL);
 
        V_BoundOffsets ();
                
 // set up gun position
-       VectorCopy (cl.viewangles, view->angles);
+       VectorCopy (cl.viewangles, view->render.angles);
        
        CalcGunAngle ();
 
-       VectorCopy (ent->origin, view->origin);
-       view->origin[2] += cl.viewheight;
+       VectorCopy (ent->render.origin, view->render.origin);
+       view->render.origin[2] += cl.viewheight;
 
        for (i=0 ; i<3 ; i++)
        {
-               view->origin[i] += forward[i]*bob*0.4;
+               view->render.origin[i] += forward[i]*bob*0.4;
 //             view->origin[i] += right[i]*bob*0.4;
 //             view->origin[i] += up[i]*bob*0.8;
        }
-       view->origin[2] += bob;
+       view->render.origin[2] += bob;
 
 // fudge position around to keep amount of weapon visible
 // roughly equal with different FOV
 
-       view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
-       view->frame = cl.stats[STAT_WEAPONFRAME];
-       view->colormap = -1; // no special coloring
+       view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]];
+       view->render.frame = cl.stats[STAT_WEAPONFRAME];
+       view->render.colormap = -1; // no special coloring
 
 // set up the refresh position
        if (!intimerefresh)
@@ -817,7 +814,7 @@ void V_CalcRefdef (void)
        }
 
 // smooth out stair step ups
-if (cl.onground && ent->origin[2] - oldz > 0)
+if (cl.onground && ent->render.origin[2] - oldz > 0)
 {
        float steptime;
        
@@ -827,15 +824,15 @@ if (cl.onground && ent->origin[2] - oldz > 0)
                steptime = 0;
 
        oldz += steptime * 80;
-       if (oldz > ent->origin[2])
-               oldz = ent->origin[2];
-       if (ent->origin[2] - oldz > 12)
-               oldz = ent->origin[2] - 12;
-       r_refdef.vieworg[2] += oldz - ent->origin[2];
-       view->origin[2] += oldz - ent->origin[2];
+       if (oldz > ent->render.origin[2])
+               oldz = ent->render.origin[2];
+       if (ent->render.origin[2] - oldz > 12)
+               oldz = ent->render.origin[2] - 12;
+       r_refdef.vieworg[2] += oldz - ent->render.origin[2];
+       view->render.origin[2] += oldz - ent->render.origin[2];
 }
 else
-       oldz = ent->origin[2];
+       oldz = ent->render.origin[2];
 
 // LordHavoc: origin view kick
        VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg);