mirror of
https://git.code.sf.net/p/quake/quakeforge-old
synced 2024-11-10 14:42:06 +00:00
925344be77
I also merged console.[ch] while I was at it..
220 lines
5.2 KiB
C
220 lines
5.2 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
// cl_parse.c -- parse a message received from the server
|
|
|
|
#include "quakedef.h"
|
|
#include "glquake.h"
|
|
#include <protocol.h>
|
|
#include <sys.h>
|
|
#include <mathlib.h>
|
|
|
|
entity_t *CL_EntityNum (int num);
|
|
|
|
/*
|
|
==================
|
|
CL_ParseUpdate
|
|
|
|
Parse an entity update message from the server
|
|
If an entities model or origin changes from frame to frame, it must be
|
|
relinked. Other attributes can change without relinking.
|
|
==================
|
|
*/
|
|
int bitcounts[16];
|
|
|
|
void CL_ParseUpdate (int bits)
|
|
{
|
|
model_t *model;
|
|
qboolean forcelink;
|
|
entity_t *ent;
|
|
int modnum, num, i;
|
|
|
|
if (cls.signon == SIGNONS - 1)
|
|
{ // first update is the final signon stage
|
|
cls.signon = SIGNONS;
|
|
CL_SignonReply ();
|
|
}
|
|
|
|
if (bits & U_MOREBITS)
|
|
{
|
|
i = MSG_ReadByte ();
|
|
bits |= (i<<8);
|
|
}
|
|
|
|
if (bits & U_LONGENTITY)
|
|
num = MSG_ReadShort ();
|
|
else
|
|
num = MSG_ReadByte ();
|
|
|
|
ent = CL_EntityNum (num);
|
|
|
|
for (i=0 ; i<16 ; i++)
|
|
if (bits&(1<<i))
|
|
bitcounts[i]++;
|
|
|
|
if (ent->msgtime != cl.mtime[1])
|
|
forcelink = true; // no previous frame to lerp from
|
|
else
|
|
forcelink = false;
|
|
|
|
ent->msgtime = cl.mtime[0];
|
|
|
|
if (bits & U_MODEL)
|
|
{
|
|
modnum = MSG_ReadByte ();
|
|
if (modnum >= MAX_MODELS)
|
|
Host_Error ("CL_ParseModel: bad modnum");
|
|
}
|
|
else
|
|
modnum = ent->baseline.modelindex;
|
|
|
|
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)
|
|
{
|
|
if (model->synctype == ST_RAND)
|
|
ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
|
|
else
|
|
ent->syncbase = 0.0;
|
|
}
|
|
else
|
|
forcelink = true; // hack to make null model players work
|
|
if (num > 0 && num <= cl.maxclients)
|
|
R_TranslatePlayerSkin (num - 1);
|
|
}
|
|
|
|
if (bits & U_FRAME)
|
|
ent->frame = MSG_ReadByte ();
|
|
else
|
|
ent->frame = ent->baseline.frame;
|
|
|
|
if (bits & U_COLORMAP)
|
|
i = MSG_ReadByte();
|
|
else
|
|
i = ent->baseline.colormap;
|
|
if (!i)
|
|
ent->colormap = vid.colormap;
|
|
else
|
|
{
|
|
if (i > cl.maxclients)
|
|
Sys_Error ("i >= cl.maxclients");
|
|
ent->colormap = cl.scores[i-1].translations;
|
|
}
|
|
|
|
{
|
|
int skin;
|
|
|
|
if (bits & U_SKIN)
|
|
skin = MSG_ReadByte();
|
|
else
|
|
skin = ent->baseline.skinnum;
|
|
if (skin != ent->skinnum) {
|
|
ent->skinnum = skin;
|
|
if (num > 0 && num <= cl.maxclients)
|
|
R_TranslatePlayerSkin (num - 1);
|
|
}
|
|
}
|
|
|
|
if (bits & U_EFFECTS)
|
|
ent->effects = MSG_ReadByte();
|
|
else
|
|
ent->effects = ent->baseline.effects;
|
|
|
|
// shift the known values for interpolation
|
|
VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
|
|
VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
|
|
|
|
if (bits & U_ORIGIN1)
|
|
ent->msg_origins[0][0] = MSG_ReadCoord ();
|
|
else
|
|
ent->msg_origins[0][0] = ent->baseline.origin[0];
|
|
if (bits & U_ANGLE1)
|
|
ent->msg_angles[0][0] = MSG_ReadAngle();
|
|
else
|
|
ent->msg_angles[0][0] = ent->baseline.angles[0];
|
|
|
|
if (bits & U_ORIGIN2)
|
|
ent->msg_origins[0][1] = MSG_ReadCoord ();
|
|
else
|
|
ent->msg_origins[0][1] = ent->baseline.origin[1];
|
|
if (bits & U_ANGLE2)
|
|
ent->msg_angles[0][1] = MSG_ReadAngle();
|
|
else
|
|
ent->msg_angles[0][1] = ent->baseline.angles[1];
|
|
|
|
if (bits & U_ORIGIN3)
|
|
ent->msg_origins[0][2] = MSG_ReadCoord ();
|
|
else
|
|
ent->msg_origins[0][2] = ent->baseline.origin[2];
|
|
if (bits & U_ANGLE3)
|
|
ent->msg_angles[0][2] = MSG_ReadAngle();
|
|
else
|
|
ent->msg_angles[0][2] = ent->baseline.angles[2];
|
|
|
|
if ( bits & U_NOLERP )
|
|
ent->forcelink = true;
|
|
|
|
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;
|
|
}
|
|
}
|
|
/*
|
|
=====================
|
|
CL_NewTranslation
|
|
=====================
|
|
*/
|
|
void CL_NewTranslation (int slot)
|
|
{
|
|
int i, j;
|
|
int top, bottom;
|
|
byte *dest, *source;
|
|
|
|
if (slot > cl.maxclients)
|
|
Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
|
|
dest = cl.scores[slot].translations;
|
|
source = vid.colormap;
|
|
memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
|
|
top = cl.scores[slot].colors & 0xf0;
|
|
bottom = (cl.scores[slot].colors &15)<<4;
|
|
R_TranslatePlayerSkin (slot);
|
|
|
|
for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
|
|
{
|
|
if (top < 128) // the artists made some backwards ranges. sigh.
|
|
memcpy (dest + TOP_RANGE, source + top, 16);
|
|
else
|
|
for (j=0 ; j<16 ; j++)
|
|
dest[TOP_RANGE+j] = source[top+15-j];
|
|
|
|
if (bottom < 128)
|
|
memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
|
|
else
|
|
for (j=0 ; j<16 ; j++)
|
|
dest[BOTTOM_RANGE+j] = source[bottom+15-j];
|
|
}
|
|
}
|