#include "client.h"
extern struct model_s *cl_mod_powerscreen;
int vidref_val;
#if 0#endif
int bitcounts[32]; int CL_ParseEntityBits(uint32_t *bits) {
unsigned b, total;
int i;
int number;
total = MSG_ReadByte(&net_message);
if(total & U_MOREBITS1) {
b = MSG_ReadByte(&net_message);
total |= b << 8;
}
if(total & U_MOREBITS2) {
b = MSG_ReadByte(&net_message);
total |= b << 16;
}
if(total & U_MOREBITS3) {
b = MSG_ReadByte(&net_message);
total |= b << 24;
}
for(i = 0; i < 32; i++)
if(total & (1 << i))
bitcounts[i]++;
if(total & U_NUMBER16)
number = MSG_ReadShort(&net_message);
else
number = MSG_ReadByte(&net_message);
*bits = total;
return number;
}
void CL_ParseDelta(entity_state_t *from, entity_state_t *to, int number, int bits) {
*to = *from;
VectorCopy(from->origin, to->old_origin);
to->number = number;
if(bits & U_MODEL)
to->modelindex = MSG_ReadByte(&net_message);
if(bits & U_MODEL2)
to->modelindex2 = MSG_ReadByte(&net_message);
if(bits & U_MODEL3)
to->modelindex3 = MSG_ReadByte(&net_message);
if(bits & U_MODEL4)
to->modelindex4 = MSG_ReadByte(&net_message);
if(bits & U_FRAME8)
to->frame = MSG_ReadByte(&net_message);
if(bits & U_FRAME16)
to->frame = MSG_ReadShort(&net_message);
if((bits & U_SKIN8) && (bits & U_SKIN16)) to->skinnum = MSG_ReadLong(&net_message);
else if(bits & U_SKIN8)
to->skinnum = MSG_ReadByte(&net_message);
else if(bits & U_SKIN16)
to->skinnum = MSG_ReadShort(&net_message);
if((bits & (U_EFFECTS8 | U_EFFECTS16)) == (U_EFFECTS8 | U_EFFECTS16))
to->effects = MSG_ReadLong(&net_message);
else if(bits & U_EFFECTS8)
to->effects = MSG_ReadByte(&net_message);
else if(bits & U_EFFECTS16)
to->effects = MSG_ReadShort(&net_message);
if((bits & (U_RENDERFX8 | U_RENDERFX16)) == (U_RENDERFX8 | U_RENDERFX16))
to->renderfx = MSG_ReadLong(&net_message);
else if(bits & U_RENDERFX8)
to->renderfx = MSG_ReadByte(&net_message);
else if(bits & U_RENDERFX16)
to->renderfx = MSG_ReadShort(&net_message);
if(bits & U_ORIGIN1)
to->origin[0] = MSG_ReadCoord(&net_message);
if(bits & U_ORIGIN2)
to->origin[1] = MSG_ReadCoord(&net_message);
if(bits & U_ORIGIN3)
to->origin[2] = MSG_ReadCoord(&net_message);
if(bits & U_ANGLE1)
to->angles[0] = MSG_ReadAngle(&net_message);
if(bits & U_ANGLE2)
to->angles[1] = MSG_ReadAngle(&net_message);
if(bits & U_ANGLE3)
to->angles[2] = MSG_ReadAngle(&net_message);
if(bits & U_OLDORIGIN)
MSG_ReadPos(&net_message, to->old_origin);
if(bits & U_SOUND)
to->sound = MSG_ReadByte(&net_message);
if(bits & U_EVENT)
to->event = MSG_ReadByte(&net_message);
else
to->event = 0;
if(bits & U_SOLID)
to->solid = MSG_ReadShort(&net_message);
if(bits & U_CMODEL_INDEX)
to->cmodel_index = MSG_ReadByte(&net_message);
}
void CL_DeltaEntity(frame_t *frame, int newnum, entity_state_t *old, int bits) {
centity_t *ent;
entity_state_t *state;
ent = &cl_entities[newnum];
state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES - 1)];
cl.parse_entities++;
frame->num_entities++;
CL_ParseDelta(old, state, newnum, bits);
if(state->modelindex != ent->current.modelindex || state->modelindex2 != ent->current.modelindex2 ||
state->modelindex3 != ent->current.modelindex3 || state->modelindex4 != ent->current.modelindex4 ||
abs(state->origin[0] - ent->current.origin[0]) > 512 || abs(state->origin[1] - ent->current.origin[1]) > 512 ||
abs(state->origin[2] - ent->current.origin[2]) > 512 || state->event == EV_PLAYER_TELEPORT ||
state->event == EV_OTHER_TELEPORT) {
ent->serverframe = -99;
}
if(ent->serverframe != cl.frame.serverframe - 1) { ent->trailcount = 1024; ent->prev = *state;
if(state->event == EV_OTHER_TELEPORT) {
VectorCopy(state->origin, ent->prev.origin);
VectorCopy(state->origin, ent->lerp_origin);
} else {
VectorCopy(state->old_origin, ent->prev.origin);
VectorCopy(state->old_origin, ent->lerp_origin);
}
} else { ent->prev = ent->current;
}
ent->serverframe = cl.frame.serverframe;
ent->current = *state;
}
void CL_ParsePacketEntities(frame_t *oldframe, frame_t *newframe) {
int newnum;
uint32_t bits;
entity_state_t *oldstate;
int oldindex, oldnum;
newframe->parse_entities = cl.parse_entities;
newframe->num_entities = 0;
oldindex = 0;
if(!oldframe)
oldnum = 99999;
else {
if(oldindex >= oldframe->num_entities)
oldnum = 99999;
else {
oldstate = &cl_parse_entities[(oldframe->parse_entities + oldindex) & (MAX_PARSE_ENTITIES - 1)];
oldnum = oldstate->number;
}
}
while(1) {
newnum = CL_ParseEntityBits(&bits);
if(newnum >= MAX_EDICTS)
Com_Error(ERR_DROP, "CL_ParsePacketEntities: bad number:%i", newnum);
if(net_message.readcount > net_message.cursize)
Com_Error(ERR_DROP, "CL_ParsePacketEntities: end of message");
if(!newnum)
break;
while(oldnum < newnum) { if(cl_shownet->value == 3)
Com_Printf(" unchanged: %i\n", oldnum);
CL_DeltaEntity(newframe, oldnum, oldstate, 0);
oldindex++;
if(oldindex >= oldframe->num_entities)
oldnum = 99999;
else {
oldstate = &cl_parse_entities[(oldframe->parse_entities + oldindex) & (MAX_PARSE_ENTITIES - 1)];
oldnum = oldstate->number;
}
}
if(bits & U_REMOVE) { if(cl_shownet->value == 3)
Com_Printf(" remove: %i\n", newnum);
if(oldnum != newnum)
Com_Printf("U_REMOVE: oldnum != newnum\n");
oldindex++;
if(oldindex >= oldframe->num_entities)
oldnum = 99999;
else {
oldstate = &cl_parse_entities[(oldframe->parse_entities + oldindex) & (MAX_PARSE_ENTITIES - 1)];
oldnum = oldstate->number;
}
continue;
}
if(oldnum == newnum) { if(cl_shownet->value == 3)
Com_Printf(" delta: %i\n", newnum);
CL_DeltaEntity(newframe, newnum, oldstate, bits);
oldindex++;
if(oldindex >= oldframe->num_entities)
oldnum = 99999;
else {
oldstate = &cl_parse_entities[(oldframe->parse_entities + oldindex) & (MAX_PARSE_ENTITIES - 1)];
oldnum = oldstate->number;
}
continue;
}
if(oldnum > newnum) { if(cl_shownet->value == 3)
Com_Printf(" baseline: %i\n", newnum);
CL_DeltaEntity(newframe, newnum, &cl_entities[newnum].baseline, bits);
continue;
}
}
while(oldnum != 99999) { if(cl_shownet->value == 3)
Com_Printf(" unchanged: %i\n", oldnum);
CL_DeltaEntity(newframe, oldnum, oldstate, 0);
oldindex++;
if(oldindex >= oldframe->num_entities)
oldnum = 99999;
else {
oldstate = &cl_parse_entities[(oldframe->parse_entities + oldindex) & (MAX_PARSE_ENTITIES - 1)];
oldnum = oldstate->number;
}
}
}
void CL_ParsePlayerstate(frame_t *oldframe, frame_t *newframe) {
int flags;
player_state_t *state;
int i;
int statbits;
state = &newframe->playerstate;
if(oldframe)
*state = oldframe->playerstate;
else
memset(state, 0, sizeof(*state));
flags = MSG_ReadShort(&net_message);
if(flags & PS_M_TYPE)
state->pmove.pm_type = MSG_ReadByte(&net_message);
if(flags & PS_M_ORIGIN) {
state->pmove.origin[0] = MSG_ReadShort(&net_message);
state->pmove.origin[1] = MSG_ReadShort(&net_message);
state->pmove.origin[2] = MSG_ReadShort(&net_message);
}
if(flags & PS_M_VELOCITY) {
state->pmove.velocity[0] = MSG_ReadShort(&net_message);
state->pmove.velocity[1] = MSG_ReadShort(&net_message);
state->pmove.velocity[2] = MSG_ReadShort(&net_message);
}
if(flags & PS_M_TIME)
state->pmove.pm_time = MSG_ReadByte(&net_message);
if(flags & PS_M_FLAGS)
state->pmove.pm_flags = MSG_ReadByte(&net_message);
if(flags & PS_M_GRAVITY)
state->pmove.gravity = MSG_ReadShort(&net_message);
if(flags & PS_M_DELTA_ANGLES) {
state->pmove.delta_angles[0] = MSG_ReadShort(&net_message);
state->pmove.delta_angles[1] = MSG_ReadShort(&net_message);
state->pmove.delta_angles[2] = MSG_ReadShort(&net_message);
}
if(cl.attractloop)
state->pmove.pm_type = PM_FREEZE;
if(flags & PS_VIEWOFFSET) {
state->viewoffset[0] = MSG_ReadChar(&net_message) * 0.25;
state->viewoffset[1] = MSG_ReadChar(&net_message) * 0.25;
state->viewoffset[2] = MSG_ReadChar(&net_message) * 0.25;
}
if(flags & PS_VIEWANGLES) {
state->viewangles[0] = MSG_ReadAngle16(&net_message);
state->viewangles[1] = MSG_ReadAngle16(&net_message);
state->viewangles[2] = MSG_ReadAngle16(&net_message);
}
if(flags & PS_KICKANGLES) {
state->kick_angles[0] = MSG_ReadChar(&net_message) * 0.25;
state->kick_angles[1] = MSG_ReadChar(&net_message) * 0.25;
state->kick_angles[2] = MSG_ReadChar(&net_message) * 0.25;
}
if(flags & PS_WEAPONINDEX) {
state->gunindex = MSG_ReadByte(&net_message);
}
if(flags & PS_WEAPONFRAME) {
state->gunframe = MSG_ReadByte(&net_message);
state->gunoffset[0] = MSG_ReadChar(&net_message) * 0.25;
state->gunoffset[1] = MSG_ReadChar(&net_message) * 0.25;
state->gunoffset[2] = MSG_ReadChar(&net_message) * 0.25;
state->gunangles[0] = MSG_ReadChar(&net_message) * 0.25;
state->gunangles[1] = MSG_ReadChar(&net_message) * 0.25;
state->gunangles[2] = MSG_ReadChar(&net_message) * 0.25;
}
if(flags & PS_BLEND) {
state->blend[0] = MSG_ReadByte(&net_message) / 255.0;
state->blend[1] = MSG_ReadByte(&net_message) / 255.0;
state->blend[2] = MSG_ReadByte(&net_message) / 255.0;
state->blend[3] = MSG_ReadByte(&net_message) / 255.0;
}
if(flags & PS_FOV)
state->fov = MSG_ReadByte(&net_message);
if(flags & PS_RDFLAGS)
state->rdflags = MSG_ReadByte(&net_message);
if(flags & PS_CMODEL_INDEX)
state->cmodel_index = MSG_ReadByte(&net_message);
statbits = MSG_ReadLong(&net_message);
for(i = 0; i < MAX_STATS; i++)
if(statbits & (1 << i))
state->stats[i] = MSG_ReadShort(&net_message);
}
void CL_FireEntityEvents(frame_t *frame) {
entity_state_t *s1;
int pnum, num;
for(pnum = 0; pnum < frame->num_entities; pnum++) {
num = (frame->parse_entities + pnum) & (MAX_PARSE_ENTITIES - 1);
s1 = &cl_parse_entities[num];
if(s1->event)
CL_EntityEvent(s1);
}
}
void CL_ParseFrame(void) {
int cmd;
int len;
frame_t *old;
memset(&cl.frame, 0, sizeof(cl.frame));
#if 0#endif
cl.frame.serverframe = MSG_ReadLong(&net_message);
cl.frame.deltaframe = MSG_ReadLong(&net_message);
cl.frame.servertime = cl.frame.serverframe * 100;
if(cls.serverProtocol != 26)
cl.surpressCount = MSG_ReadByte(&net_message);
if(cl_shownet->value == 3)
Com_Printf(" frame:%i delta:%i\n", cl.frame.serverframe, cl.frame.deltaframe);
if(cl.frame.deltaframe <= 0) {
cl.frame.valid = true; old = NULL;
cls.demowaiting = false; } else {
old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
if(!old->valid) { Com_Printf("Delta from invalid frame (not supposed to happen!).\n");
}
if(old->serverframe != cl.frame.deltaframe) { Com_Printf("Delta frame too old.\n");
} else if(cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES - 128) {
Com_Printf("Delta parse_entities too old.\n");
} else
cl.frame.valid = true; }
if(cl.time > cl.frame.servertime)
cl.time = cl.frame.servertime;
else if(cl.time < cl.frame.servertime - 100)
cl.time = cl.frame.servertime - 100;
len = MSG_ReadByte(&net_message);
MSG_ReadData(&net_message, &cl.frame.areabits, len);
cmd = MSG_ReadByte(&net_message);
SHOWNET(svc_strings[cmd]);
if(cmd != svc_playerinfo)
Com_Error(ERR_DROP, "CL_ParseFrame: not playerinfo");
CL_ParsePlayerstate(old, &cl.frame);
cmd = MSG_ReadByte(&net_message);
SHOWNET(svc_strings[cmd]);
if(cmd != svc_packetentities)
Com_Error(ERR_DROP, "CL_ParseFrame: not packetentities");
CL_ParsePacketEntities(old, &cl.frame);
#if 0#endif
cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame;
if(cl.frame.valid) {
if(cls.state != ca_active) {
cls.state = ca_active;
cl.force_refdef = true;
cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0] * 0.125;
cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1] * 0.125;
cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2] * 0.125;
VectorCopy(cl.frame.playerstate.viewangles, cl.predicted_angles);
if(cls.disable_servercount != cl.servercount && cl.refresh_prepped)
SCR_EndLoadingPlaque(); }
cl.sound_prepped = true;
CL_FireEntityEvents(&cl.frame);
CL_CheckPredictionError();
}
}
struct model_s *S_RegisterSexedModel(entity_state_t *ent, char *base) {
int n;
char *p;
struct model_s *mdl;
char model[MAX_QPATH];
char buffer[MAX_QPATH];
model[0] = 0;
n = CS_PLAYERSKINS + ent->number - 1;
if(cl.configstrings[n][0]) {
p = strchr(cl.configstrings[n], '\\');
if(p) {
p += 1;
strcpy(model, p);
p = strchr(model, '/');
if(p)
*p = 0;
}
}
if(!model[0])
strcpy(model, "male");
Com_sprintf(buffer, sizeof(buffer), "players/%s/%s", model, base + 1);
mdl = re.RegisterModel(CMODEL_A, buffer);
if(!mdl) {
Com_sprintf(buffer, sizeof(buffer), "players/%s/weapon.md2", model);
mdl = re.RegisterModel(CMODEL_A, buffer);
if(!mdl) {
Com_sprintf(buffer, sizeof(buffer), "players/%s/%s", "male", base + 1);
mdl = re.RegisterModel(CMODEL_A, buffer);
if(!mdl) {
Com_sprintf(buffer, sizeof(buffer), "players/male/weapon.md2");
mdl = re.RegisterModel(CMODEL_A, buffer);
}
}
}
return mdl;
}
void CL_AddPacketEntities(frame_t *frame) {
entity_t ent;
entity_state_t *s1;
float autorotate;
int i;
int pnum;
centity_t *cent;
int autoanim;
clientinfo_t *ci;
unsigned int effects, renderfx;
autorotate = anglemod(cl.time / 10);
autoanim = 2 * cl.time / 1000;
memset(&ent, 0, sizeof(ent));
for(pnum = 0; pnum < frame->num_entities; pnum++) {
s1 = &cl_parse_entities[(frame->parse_entities + pnum) & (MAX_PARSE_ENTITIES - 1)];
cent = &cl_entities[s1->number];
effects = s1->effects;
renderfx = s1->renderfx;
if(effects & EF_ANIM01)
ent.frame = autoanim & 1;
else if(effects & EF_ANIM23)
ent.frame = 2 + (autoanim & 1);
else if(effects & EF_ANIM_ALL)
ent.frame = autoanim;
else if(effects & EF_ANIM_ALLFAST)
ent.frame = cl.time / 100;
else
ent.frame = s1->frame;
if(effects & EF_PENT) {
effects &= ~EF_PENT;
effects |= EF_COLOR_SHELL;
renderfx |= RF_SHELL_RED;
}
if(effects & EF_QUAD) {
effects &= ~EF_QUAD;
effects |= EF_COLOR_SHELL;
renderfx |= RF_SHELL_BLUE;
}
if(effects & EF_DOUBLE) {
effects &= ~EF_DOUBLE;
effects |= EF_COLOR_SHELL;
renderfx |= RF_SHELL_DOUBLE;
}
if(effects & EF_HALF_DAMAGE) {
effects &= ~EF_HALF_DAMAGE;
effects |= EF_COLOR_SHELL;
renderfx |= RF_SHELL_HALF_DAM;
}
ent.oldframe = cent->prev.frame;
ent.backlerp = 1.0 - cl.lerpfrac;
if(renderfx & (RF_FRAMELERP | RF_BEAM)) { VectorCopy(cent->current.origin, ent.origin);
VectorCopy(cent->current.old_origin, ent.oldorigin);
} else { for(i = 0; i < 3; i++) {
ent.origin[i] = ent.oldorigin[i] =
cent->prev.origin[i] + cl.lerpfrac * (cent->current.origin[i] - cent->prev.origin[i]);
}
}
if(renderfx & RF_BEAM) { ent.alpha = 0.30;
ent.skinnum = (s1->skinnum >> ((rand() % 4) * 8)) & 0xff;
ent.model = NULL;
} else {
if(s1->modelindex == 255) { ent.skinnum = 0;
ci = &cl.clientinfo[s1->skinnum & 0xff];
ent.skin = ci->skin;
ent.model = ci->model;
if(!ent.skin || !ent.model) {
ent.skin = cl.baseclientinfo.skin;
ent.model = cl.baseclientinfo.model;
}
if(renderfx & RF_USE_DISGUISE) {
if(!strncmp((char *)ent.skin, "players/male", 12)) {
ent.skin = re.RegisterSkin("players/male/disguise.pcx");
ent.model = re.RegisterModel(CMODEL_A, "players/male/tris.md2");
} else if(!strncmp((char *)ent.skin, "players/female", 14)) {
ent.skin = re.RegisterSkin("players/female/disguise.pcx");
ent.model = re.RegisterModel(CMODEL_A, "players/female/tris.md2");
} else if(!strncmp((char *)ent.skin, "players/cyborg", 14)) {
ent.skin = re.RegisterSkin("players/cyborg/disguise.pcx");
ent.model = re.RegisterModel(CMODEL_A, "players/cyborg/tris.md2");
}
}
} else {
ent.skinnum = s1->skinnum;
ent.skin = NULL;
if(s1->modelindex - 1 < CMODEL_COUNT) {
ent.model = cl.cmodel_draw[s1->modelindex - 1][s1->modelindex2];
} else {
ent.model = cl.model_draw[s1->modelindex];
}
}
}
if(renderfx == RF_TRANSLUCENT)
ent.alpha = 0.70;
if((effects & EF_COLOR_SHELL))
ent.flags = 0; else
ent.flags = renderfx;
if(effects & EF_ROTATE) { ent.angles[0] = 0;
ent.angles[1] = autorotate;
ent.angles[2] = 0;
}
else if(effects & EF_SPINNINGLIGHTS) {
ent.angles[0] = 0;
ent.angles[1] = anglemod(cl.time / 2) + s1->angles[1];
ent.angles[2] = 180;
{
vec3_t forward;
vec3_t start;
AngleVectors(ent.angles, forward, NULL, NULL);
VectorMA(ent.origin, 64, forward, start);
V_AddLight(start, 100, 1, 0, 0);
}
} else { float a1, a2;
for(i = 0; i < 3; i++) {
a1 = cent->current.angles[i];
a2 = cent->prev.angles[i];
ent.angles[i] = LerpAngle(a2, a1, cl.lerpfrac);
}
}
if(s1->number == cl.playernum + 1) {
ent.flags |= RF_VIEWERMODEL;
if(effects & EF_FLAG1)
V_AddLight(ent.origin, 225, 1.0, 0.1, 0.1);
else if(effects & EF_FLAG2)
V_AddLight(ent.origin, 225, 0.1, 0.1, 1.0);
else if(effects & EF_TAGTRAIL) V_AddLight(ent.origin, 225, 1.0, 1.0, 0.0); else if(effects & EF_TRACKERTRAIL) V_AddLight(ent.origin, 225, -1.0, -1.0, -1.0);
continue;
}
if(!s1->modelindex)
continue;
if(effects & EF_BFG) {
ent.flags |= RF_TRANSLUCENT;
ent.alpha = 0.30;
}
if(effects & EF_PLASMA) {
ent.flags |= RF_TRANSLUCENT;
ent.alpha = 0.6;
}
if(effects & EF_SPHERETRANS) {
ent.flags |= RF_TRANSLUCENT;
if(effects & EF_TRACKERTRAIL)
ent.alpha = 0.6;
else
ent.alpha = 0.3;
}
V_AddEntity(&ent);
if(effects & EF_COLOR_SHELL) {
ent.flags = renderfx | RF_TRANSLUCENT;
ent.alpha = 0.30;
V_AddEntity(&ent);
}
ent.skin = NULL; ent.skinnum = 0;
ent.flags = 0;
ent.alpha = 0;
if((s1->modelindex - 1 >= CMODEL_COUNT) && s1->modelindex2) {
if(s1->modelindex2 == 255) { ci = &cl.clientinfo[s1->skinnum & 0xff];
i = (s1->skinnum >> 8); if(!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1)
i = 0;
ent.model = ci->weaponmodel[i];
if(!ent.model) {
if(i != 0)
ent.model = ci->weaponmodel[0];
if(!ent.model)
ent.model = cl.baseclientinfo.weaponmodel[0];
}
}
else if(s1->modelindex2 & 0x80) {
ent.model = cl.model_draw[s1->modelindex2 & 0x7F];
ent.alpha = 0.32;
ent.flags = RF_TRANSLUCENT;
} else {
ent.model = cl.model_draw[s1->modelindex2];
}
V_AddEntity(&ent);
ent.flags = 0;
ent.alpha = 0;
}
if(s1->modelindex3) {
ent.model = cl.model_draw[s1->modelindex3];
V_AddEntity(&ent);
}
if(s1->modelindex4) {
ent.model = cl.model_draw[s1->modelindex4];
V_AddEntity(&ent);
}
if(effects & EF_POWERSCREEN) {
ent.model = cl_mod_powerscreen;
ent.oldframe = 0;
ent.frame = 0;
ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
ent.alpha = 0.30;
V_AddEntity(&ent);
}
if(s1->effects & EF_TELEPORTER)
CL_TeleporterParticles(s1);
if((effects & ~EF_ROTATE)) {
if(effects & EF_ROCKET) {
CL_RocketTrail(cent->lerp_origin, ent.origin, cent);
V_AddLight(ent.origin, 200, 1, 1, 0);
}
else if(effects & EF_BLASTER) {
if(effects & EF_TRACKER) {
CL_BlasterTrail2(cent->lerp_origin, ent.origin);
V_AddLight(ent.origin, 200, 0, 1, 0);
} else {
CL_BlasterTrail(cent->lerp_origin, ent.origin);
V_AddLight(ent.origin, 200, 1, 1, 0);
}
} else if(effects & EF_HYPERBLASTER) {
if(effects & EF_TRACKER) V_AddLight(ent.origin, 200, 0, 1, 0); else V_AddLight(ent.origin, 200, 1, 1, 0);
} else if(effects & EF_GIB) {
CL_DiminishingTrail(cent->lerp_origin, ent.origin, cent, effects);
} else if(effects & EF_GRENADE) {
CL_DiminishingTrail(cent->lerp_origin, ent.origin, cent, effects);
} else if(effects & EF_FLIES) {
CL_FlyEffect(cent, ent.origin);
} else if(effects & EF_BFG) {
static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
if(effects & EF_ANIM_ALLFAST) {
CL_BfgParticles(&ent);
i = 200;
} else {
i = bfg_lightramp[s1->frame];
}
V_AddLight(ent.origin, i, 0, 1, 0);
}
else if(effects & EF_TRAP) {
ent.origin[2] += 32;
CL_TrapParticles(&ent);
i = (rand() % 100) + 100;
V_AddLight(ent.origin, i, 1, 0.8, 0.1);
} else if(effects & EF_FLAG1) {
CL_FlagTrail(cent->lerp_origin, ent.origin, 242);
V_AddLight(ent.origin, 225, 1, 0.1, 0.1);
} else if(effects & EF_FLAG2) {
CL_FlagTrail(cent->lerp_origin, ent.origin, 115);
V_AddLight(ent.origin, 225, 0.1, 0.1, 1);
}
else if(effects & EF_TAGTRAIL) {
CL_TagTrail(cent->lerp_origin, ent.origin, 220);
V_AddLight(ent.origin, 225, 1.0, 1.0, 0.0);
} else if(effects & EF_TRACKERTRAIL) {
if(effects & EF_TRACKER) {
float intensity;
intensity = 50 + (500 * (sin(cl.time / 500.0) + 1.0));
if(vidref_val == VIDREF_GL)
V_AddLight(ent.origin, intensity, -1.0, -1.0, -1.0);
else
V_AddLight(ent.origin, -1.0 * intensity, 1.0, 1.0, 1.0);
} else {
CL_Tracker_Shell(cent->lerp_origin);
V_AddLight(ent.origin, 155, -1.0, -1.0, -1.0);
}
} else if(effects & EF_TRACKER) {
CL_TrackerTrail(cent->lerp_origin, ent.origin, 0);
if(vidref_val == VIDREF_GL)
V_AddLight(ent.origin, 200, -1, -1, -1);
else
V_AddLight(ent.origin, -200, 1, 1, 1);
}
else if(effects & EF_GREENGIB) {
CL_DiminishingTrail(cent->lerp_origin, ent.origin, cent, effects);
}
else if(effects & EF_IONRIPPER) {
CL_IonripperTrail(cent->lerp_origin, ent.origin);
V_AddLight(ent.origin, 100, 1, 0.5, 0.5);
}
else if(effects & EF_BLUEHYPERBLASTER) {
V_AddLight(ent.origin, 200, 0, 0, 1);
}
else if(effects & EF_PLASMA) {
if(effects & EF_ANIM_ALLFAST) {
CL_BlasterTrail(cent->lerp_origin, ent.origin);
}
V_AddLight(ent.origin, 130, 1, 0.5, 0.5);
}
}
VectorCopy(ent.origin, cent->lerp_origin);
}
}
void CL_AddViewWeapon(player_state_t *ps, player_state_t *ops) {
entity_t gun; int i;
if(!cl_gun->value)
return;
if(ps->fov > 90)
return;
memset(&gun, 0, sizeof(gun));
if(gun_model)
gun.model = gun_model; else
gun.model = cl.model_draw[ps->gunindex];
if(!gun.model)
return;
for(i = 0; i < 3; i++) {
gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i] + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle(ops->gunangles[i], ps->gunangles[i], cl.lerpfrac);
}
if(gun_frame) {
gun.frame = gun_frame; gun.oldframe = gun_frame; } else {
gun.frame = ps->gunframe;
if(gun.frame == 0)
gun.oldframe = 0; else
gun.oldframe = ops->gunframe;
}
gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
gun.backlerp = 1.0 - cl.lerpfrac;
VectorCopy(gun.origin, gun.oldorigin); V_AddEntity(&gun);
}
void CL_CalcViewValues(void) {
int i;
float lerp, backlerp;
frame_t *oldframe;
player_state_t *ps, *ops;
ps = &cl.frame.playerstate;
i = (cl.frame.serverframe - 1) & UPDATE_MASK;
oldframe = &cl.frames[i];
if(oldframe->serverframe != cl.frame.serverframe - 1 || !oldframe->valid)
oldframe = &cl.frame; ops = &oldframe->playerstate;
if(fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256 * 8 ||
abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256 * 8 ||
abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256 * 8)
ops = ps;
lerp = cl.lerpfrac;
if((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION)) { unsigned delta;
backlerp = 1.0 - lerp;
for(i = 0; i < 3; i++) {
cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] +
cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i]) - backlerp * cl.prediction_error[i];
}
delta = cls.realtime - cl.predicted_step_time;
if(delta < 100)
cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
} else { for(i = 0; i < 3; i++)
cl.refdef.vieworg[i] = ops->pmove.origin[i] * 0.125 + ops->viewoffset[i] +
lerp * (ps->pmove.origin[i] * 0.125 + ps->viewoffset[i] -
(ops->pmove.origin[i] * 0.125 + ops->viewoffset[i]));
}
if(cl.frame.playerstate.pmove.pm_type < PM_DEAD) { for(i = 0; i < 3; i++)
cl.refdef.viewangles[i] = cl.predicted_angles[i];
} else { for(i = 0; i < 3; i++)
cl.refdef.viewangles[i] = LerpAngle(ops->viewangles[i], ps->viewangles[i], lerp);
}
for(i = 0; i < 3; i++)
cl.refdef.viewangles[i] += LerpAngle(ops->kick_angles[i], ps->kick_angles[i], lerp);
AngleVectors(cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
for(i = 0; i < 4; i++)
cl.refdef.blend[i] = ps->blend[i];
CL_AddViewWeapon(ps, ops);
}
void CL_AddEntities(void) {
if(cls.state != ca_active)
return;
if(cl.time > cl.frame.servertime) {
if(cl_showclamp->value)
Com_Printf("high clamp %i\n", cl.time - cl.frame.servertime);
cl.time = cl.frame.servertime;
cl.lerpfrac = 1.0;
} else if(cl.time < cl.frame.servertime - 100) {
if(cl_showclamp->value)
Com_Printf("low clamp %i\n", cl.frame.servertime - 100 - cl.time);
cl.time = cl.frame.servertime - 100;
cl.lerpfrac = 0;
} else
cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01;
if(cl_timedemo->value)
cl.lerpfrac = 1.0;
CL_CalcViewValues();
CL_AddPacketEntities(&cl.frame);
#if 0#endif
CL_AddTEnts();
CL_AddDLights();
CL_AddLightStyles();
}
void CL_GetEntitySoundOrigin(int ent, vec3_t org) {
centity_t *old;
if(ent < 0 || ent >= MAX_EDICTS)
Com_Error(ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
old = &cl_entities[ent];
VectorCopy(old->lerp_origin, org);
}