epair_t *epairs;
} entity_t;
-extern int num_entities;
+//extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void ParseEntities (void);
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;
}
}
}
{
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)
{
// 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;
}
//
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]);
}
}
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);
+}
+
/*
===============
float frac, f, d;
vec3_t delta;
float bobjrotate;
+// float bobjoffset;
vec3_t oldorg;
// determine partial update time
//
// 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)
}
}
- 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");
}
*/
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];
}
// 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 ();
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;
+ }
+}
/*
==================
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
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)
}
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
*/
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);
}
*/
void CL_ParseClientdata (int bits)
{
- int i, j;
+ int i, j;
bits &= 0xFFFF;
if (bits & SU_EXTEND1)
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);
}
void CL_ParseServerMessage (void)
{
int cmd;
- int i;
+ int i, updateend;
byte cmdlog[32];
char *cmdlogname[32], *temp;
int cmdindex, cmdcount = 0;
// parse the message
//
MSG_BeginReading ();
+
+ updateend = false;
while (1)
{
if (cmd == -1)
{
SHOWNET("END OF MESSAGE");
- return; // end of message
+ break; // end of message
}
cmdindex = cmdcount & 31;
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);
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;
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;
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);
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);
}
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;
}
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)
pitch += 360;
}
- // add new entities for the lightning
+ // add new entities for the lightning
VectorCopy (b->start, org);
d = VectorNormalizeLength(dist);
while (d > 0)
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;
// 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
// 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
{
efrag_t *ef, *old, *walk, **prev;
- ef = ent->efrag;
+ ef = ent->render.efrag;
while (ef)
{
cl.free_efrags = old;
}
- ent->efrag = NULL;
+ ent->render.efrag = NULL;
}
/*
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;
}
while ((pefrag = *ppefrag) != NULL)
{
pent = pefrag->entity;
- clmodel = pent->model;
+ clmodel = pent->render.model;
switch (clmodel->type)
{
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;
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
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);
}
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;
{
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);
}
// 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;
R_SetFrustum ();
R_SetupGL ();
+ R_PrepareEntities();
+
skypolyclear();
wallpolyclear();
transpolyclear();
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
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
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++)
int relative;
int count;
- if (currententity->frame)
+ if (currententity->render.frame)
{
if (base->alternate_anims)
base = base->alternate_anims;
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();
}
}
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();
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))
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);
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++)
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);
/*-----------------------------------------------------------------*/
-#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},
/*-----------------------------------------------------------------*/
-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
#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;
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);
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)
{
}
}
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);
}
/*
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);
}
}
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);
}
/*
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;
move = -speed;
}
- ent->v.angles[1] = anglemod (current + move);
+ ent->v.angles[1] = ANGLEMOD (current + move);
}
/*
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
move = -speed;
}
- ent->v.angles[0] = anglemod (current + move);
+ ent->v.angles[0] = ANGLEMOD (current + move);
}
/*
#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)
#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
#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"
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]);
rtexture_t *rainparticletexture;
rtexture_t *bubbleparticletexture;
rtexture_t *bulletholetexture[8];
+rtexture_t *rocketglowparticletexture;
particle_t *particles;
int r_numparticles;
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()
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);
}
}
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)
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);
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)
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)
{
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);
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);
// 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);
}
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 !!!
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)
{
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
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);
}
/*
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];
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);
}
//
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;
float angledelta (float a)
{
- a = anglemod(a);
+ a = ANGLEMOD(a);
if (a > 180)
a -= 360;
return a;
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;
}
/*
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;
}
/*
{
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)
// 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;
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)
}
// smooth out stair step ups
-if (cl.onground && ent->origin[2] - oldz > 0)
+if (cl.onground && ent->render.origin[2] - oldz > 0)
{
float steptime;
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);