2004-08-23 00:15:46 +00:00
/*
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
2005-02-06 02:47:36 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-08-23 00:15:46 +00:00
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_ents.c -- entity parsing and management
# include "quakedef.h"
2004-10-19 16:10:14 +00:00
# include "particles.h"
2009-11-04 21:16:50 +00:00
# include "shader.h"
2004-08-23 00:15:46 +00:00
extern cvar_t cl_predict_players ;
extern cvar_t cl_predict_players2 ;
extern cvar_t cl_solid_players ;
extern cvar_t cl_item_bobbing ;
2005-01-17 17:40:37 +00:00
extern cvar_t r_rocketlight ;
extern cvar_t r_lightflicker ;
extern cvar_t cl_r2g ;
extern cvar_t r_powerupglow ;
2005-04-16 16:21:27 +00:00
extern cvar_t v_powerupshell ;
2005-04-26 16:04:12 +00:00
extern cvar_t cl_nolerp ;
2008-12-03 02:42:05 +00:00
extern cvar_t cl_nolerp_netquake ;
2009-11-04 21:16:50 +00:00
extern cvar_t r_torch ;
2005-01-18 20:15:20 +00:00
extern cvar_t cl_gibfilter , cl_deadbodyfilter ;
2004-08-23 00:15:46 +00:00
extern int cl_playerindex ;
static struct predicted_player {
int flags ;
qboolean active ;
vec3_t origin ; // predicted origin
2004-12-15 17:47:42 +00:00
vec3_t oldo ;
vec3_t olda ;
vec3_t oldv ;
qboolean predict ;
player_state_t * oldstate ;
2004-08-23 00:15:46 +00:00
} predicted_players [ MAX_CLIENTS ] ;
2009-07-18 20:46:42 +00:00
static void CL_LerpNetFrameState ( int fsanim , framestate_t * fs , lerpents_t * le ) ;
2005-01-18 20:15:20 +00:00
extern int cl_playerindex , cl_h_playerindex , cl_rocketindex , cl_grenadeindex , cl_gib1index , cl_gib2index , cl_gib3index ;
qboolean CL_FilterModelindex ( int modelindex , int frame )
{
if ( modelindex = = cl_playerindex )
{
2009-11-04 21:16:50 +00:00
if ( cl_deadbodyfilter . ival = = 2 )
2005-01-18 20:15:20 +00:00
{
if ( frame > = 41 & & frame < = 102 )
return true ;
}
2009-11-04 21:16:50 +00:00
else if ( cl_deadbodyfilter . ival )
2005-01-18 20:15:20 +00:00
{
if ( frame = = 49 | | frame = = 60 | | frame = = 69 | | frame = = 84 | | frame = = 93 | | frame = = 102 )
return true ;
}
}
2009-11-04 21:16:50 +00:00
if ( cl_gibfilter . ival & & (
2005-02-06 02:47:36 +00:00
modelindex = = cl_h_playerindex | |
2005-01-18 20:15:20 +00:00
modelindex = = cl_gib1index | |
modelindex = = cl_gib2index | |
modelindex = = cl_gib3index ) )
return true ;
return false ;
}
2005-01-17 17:40:37 +00:00
2004-08-23 00:15:46 +00:00
//============================================================
2009-11-04 21:16:50 +00:00
void CL_InitDlights ( void )
{
rtlights_max = cl_maxdlights = RTL_FIRST ;
cl_dlights = BZ_Realloc ( NULL , sizeof ( * cl_dlights ) * cl_maxdlights ) ;
memset ( cl_dlights , 0 , sizeof ( * cl_dlights ) * cl_maxdlights ) ;
}
2009-07-05 18:45:53 +00:00
static void CL_ClearDlight ( dlight_t * dl , int key )
{
2009-11-04 21:16:50 +00:00
texid_t st ;
2009-07-05 18:45:53 +00:00
st = dl - > stexture ;
memset ( dl , 0 , sizeof ( * dl ) ) ;
dl - > stexture = st ;
dl - > axis [ 0 ] [ 0 ] = 1 ;
dl - > axis [ 1 ] [ 1 ] = 1 ;
dl - > axis [ 2 ] [ 2 ] = 1 ;
dl - > key = key ;
dl - > flags = LFLAG_DYNAMIC ;
2009-11-04 21:16:50 +00:00
// if (r_shadow_realtime_dlight_shadowmap.value)
// dl->flags |= LFLAG_SHADOWMAP;
}
dlight_t * CL_AllocSlight ( void )
{
dlight_t * dl ;
if ( rtlights_max = = cl_maxdlights )
{
cl_maxdlights = rtlights_max + 8 ;
cl_dlights = BZ_Realloc ( cl_dlights , sizeof ( * cl_dlights ) * cl_maxdlights ) ;
memset ( & cl_dlights [ rtlights_max ] , 0 , sizeof ( * cl_dlights ) * ( cl_maxdlights - rtlights_max ) ) ;
}
dl = & cl_dlights [ rtlights_max + + ] ;
CL_ClearDlight ( dl , 0 ) ;
return dl ;
2009-07-05 18:45:53 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = =
CL_AllocDlight
= = = = = = = = = = = = = = =
*/
dlight_t * CL_AllocDlight ( int key )
{
int i ;
dlight_t * dl ;
// first look for an exact key match
if ( key )
{
2009-11-04 21:16:50 +00:00
dl = cl_dlights + rtlights_first ;
for ( i = rtlights_first ; i < RTL_FIRST ; i + + , dl + + )
2004-08-23 00:15:46 +00:00
{
if ( dl - > key = = key )
{
2009-07-05 18:45:53 +00:00
CL_ClearDlight ( dl , key ) ;
2004-08-23 00:15:46 +00:00
return dl ;
}
}
}
2009-11-04 21:16:50 +00:00
//default to the first
dl = & cl_dlights [ rtlights_first ? rtlights_first - 1 : 0 ] ;
//try and find one that is free
for ( i = RTL_FIRST ; i > rtlights_first & & i > 0 ; )
2004-08-23 00:15:46 +00:00
{
2009-11-04 21:16:50 +00:00
i - - ;
if ( ! cl_dlights [ i ] . radius )
{
dl = & cl_dlights [ i ] ;
break ;
}
2004-08-23 00:15:46 +00:00
}
2009-11-04 21:16:50 +00:00
if ( rtlights_first > dl - cl_dlights )
rtlights_first = dl - cl_dlights ;
2004-08-23 00:15:46 +00:00
2009-07-05 18:45:53 +00:00
CL_ClearDlight ( dl , key ) ;
2004-08-23 00:15:46 +00:00
return dl ;
}
/*
= = = = = = = = = = = = = = =
CL_NewDlight
= = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
dlight_t * CL_NewDlight ( int key , const vec3_t org , float radius , float time , int type )
2004-08-23 00:15:46 +00:00
{
2009-11-04 21:16:50 +00:00
static const vec3_t lightcolour [ ] =
{
{ 0.2 , 0.1 , 0.05 } ,
{ 0.05 , 0.05 , 0.3 } ,
{ 0.5 , 0.05 , 0.05 } ,
{ 0.5 , 0.05 , 0.4 }
} ;
2004-08-23 00:15:46 +00:00
dlight_t * dl ;
2009-11-04 21:16:50 +00:00
if ( type > = sizeof ( lightcolour ) / sizeof ( lightcolour [ 0 ] ) )
type = 0 ;
2004-08-23 00:15:46 +00:00
dl = CL_AllocDlight ( key ) ;
2009-11-04 21:16:50 +00:00
VectorCopy ( org , dl - > origin ) ;
2004-08-23 00:15:46 +00:00
dl - > radius = radius ;
2004-11-27 08:16:25 +00:00
dl - > die = ( float ) cl . time + time ;
2009-11-04 21:16:50 +00:00
VectorCopy ( lightcolour [ type ] , dl - > color ) ;
2004-08-23 00:15:46 +00:00
return dl ;
}
2009-11-04 21:16:50 +00:00
dlight_t * CL_NewDlightRGB ( int key , const vec3_t org , float radius , float time ,
2004-08-23 00:15:46 +00:00
float r , float g , float b )
{
dlight_t * dl ;
dl = CL_AllocDlight ( key ) ;
2009-11-04 21:16:50 +00:00
VectorCopy ( org , dl - > origin ) ;
2004-08-23 00:15:46 +00:00
dl - > radius = radius ;
dl - > die = cl . time + time ;
dl - > color [ 0 ] = r ;
dl - > color [ 1 ] = g ;
dl - > color [ 2 ] = b ;
2008-12-23 02:55:20 +00:00
return dl ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = =
CL_DecayLights
= = = = = = = = = = = = = = =
*/
void CL_DecayLights ( void )
{
int i ;
dlight_t * dl ;
if ( cl . paused ) //DON'T DO IT!!!
return ;
2009-11-04 21:16:50 +00:00
dl = cl_dlights + rtlights_first ;
for ( i = rtlights_first ; i < RTL_FIRST ; i + + , dl + + )
2004-08-23 00:15:46 +00:00
{
2004-11-27 08:16:25 +00:00
if ( ! dl - > radius )
2009-11-04 21:16:50 +00:00
{
2004-08-23 00:15:46 +00:00
continue ;
2009-11-04 21:16:50 +00:00
}
2004-11-27 08:16:25 +00:00
2009-07-05 18:45:53 +00:00
if ( ! dl - > die )
{
continue ;
}
2004-11-27 08:16:25 +00:00
if ( dl - > die < ( float ) cl . time )
{
2009-11-04 21:16:50 +00:00
if ( i = = rtlights_first )
rtlights_first + + ;
2004-11-27 08:16:25 +00:00
dl - > radius = 0 ;
continue ;
}
2005-02-06 02:47:36 +00:00
2004-08-23 00:15:46 +00:00
dl - > radius - = host_frametime * dl - > decay ;
if ( dl - > radius < 0 )
2006-05-11 03:14:41 +00:00
{
2009-11-04 21:16:50 +00:00
if ( i = = rtlights_first )
rtlights_first + + ;
2004-08-23 00:15:46 +00:00
dl - > radius = 0 ;
2006-05-11 03:14:41 +00:00
continue ;
}
2004-08-23 00:15:46 +00:00
if ( dl - > channelfade [ 0 ] )
{
2005-02-06 02:47:36 +00:00
dl - > color [ 0 ] - = host_frametime * dl - > channelfade [ 0 ] ;
2004-08-23 00:15:46 +00:00
if ( dl - > color [ 0 ] < 0 )
dl - > color [ 0 ] = 0 ;
}
if ( dl - > channelfade [ 1 ] )
{
2005-02-06 02:47:36 +00:00
dl - > color [ 1 ] - = host_frametime * dl - > channelfade [ 1 ] ;
2004-08-23 00:15:46 +00:00
if ( dl - > color [ 1 ] < 0 )
dl - > color [ 1 ] = 0 ;
}
if ( dl - > channelfade [ 2 ] )
{
2005-02-06 02:47:36 +00:00
dl - > color [ 2 ] - = host_frametime * dl - > channelfade [ 2 ] ;
2004-08-23 00:15:46 +00:00
if ( dl - > color [ 2 ] < 0 )
dl - > color [ 2 ] = 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PACKET ENTITY PARSING / LINKING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
CL_ParseDelta
Can go from either a baseline or a previous packet_entity
= = = = = = = = = = = = = = = = = =
*/
int bitcounts [ 32 ] ; /// just for protocol profiling
void CL_ParseDelta ( entity_state_t * from , entity_state_t * to , int bits , qboolean new )
{
int i ;
# ifdef PROTOCOLEXTENSIONS
int morebits = 0 ;
# endif
// set everything to the state we are delta'ing from
* to = * from ;
to - > number = bits & 511 ;
bits & = ~ 511 ;
if ( bits & U_MOREBITS )
{ // read in the low order bits
i = MSG_ReadByte ( ) ;
bits | = i ;
}
// count the bits for net profiling
for ( i = 0 ; i < 16 ; i + + )
if ( bits & ( 1 < < i ) )
bitcounts [ i ] + + ;
# ifdef PROTOCOLEXTENSIONS
2009-11-04 21:16:50 +00:00
if ( bits & U_EVENMORE & & ( cls . fteprotocolextensions & ( PEXT_SCALE | PEXT_TRANS | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_MODELDBL | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 ) ) )
2004-08-23 00:15:46 +00:00
morebits = MSG_ReadByte ( ) ;
if ( morebits & U_YETMORE )
morebits | = MSG_ReadByte ( ) < < 8 ;
# endif
if ( bits & U_MODEL )
to - > modelindex = MSG_ReadByte ( ) ;
if ( bits & U_FRAME )
to - > frame = MSG_ReadByte ( ) ;
if ( bits & U_COLORMAP )
to - > colormap = MSG_ReadByte ( ) ;
if ( bits & U_SKIN )
to - > skinnum = MSG_ReadByte ( ) ;
if ( bits & U_EFFECTS )
2005-08-26 22:56:51 +00:00
to - > effects = ( to - > effects & 0xff00 ) | MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
if ( bits & U_ORIGIN1 )
to - > origin [ 0 ] = MSG_ReadCoord ( ) ;
2005-02-06 02:47:36 +00:00
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE1 )
to - > angles [ 0 ] = MSG_ReadAngle ( ) ;
if ( bits & U_ORIGIN2 )
to - > origin [ 1 ] = MSG_ReadCoord ( ) ;
2005-02-06 02:47:36 +00:00
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE2 )
to - > angles [ 1 ] = MSG_ReadAngle ( ) ;
if ( bits & U_ORIGIN3 )
to - > origin [ 2 ] = MSG_ReadCoord ( ) ;
2005-02-06 02:47:36 +00:00
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE3 )
to - > angles [ 2 ] = MSG_ReadAngle ( ) ;
if ( bits & U_SOLID )
{
// FIXME
}
# ifdef PEXT_SCALE
if ( morebits & U_SCALE & & cls . fteprotocolextensions & PEXT_SCALE )
2005-07-01 19:23:00 +00:00
to - > scale = MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_TRANS
if ( morebits & U_TRANS & & cls . fteprotocolextensions & PEXT_TRANS )
2005-07-01 19:23:00 +00:00
to - > trans = MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_FATNESS
if ( morebits & U_FATNESS & & cls . fteprotocolextensions & PEXT_FATNESS )
2005-07-01 19:23:00 +00:00
to - > fatness = MSG_ReadChar ( ) ;
2004-08-23 00:15:46 +00:00
# endif
if ( morebits & U_DRAWFLAGS & & cls . fteprotocolextensions & PEXT_HEXEN2 )
2005-05-15 18:49:04 +00:00
to - > hexen2flags = MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
if ( morebits & U_ABSLIGHT & & cls . fteprotocolextensions & PEXT_HEXEN2 )
to - > abslight = MSG_ReadByte ( ) ;
2006-03-12 06:23:52 +00:00
if ( morebits & U_COLOURMOD & & cls . fteprotocolextensions & PEXT_COLOURMOD )
{
to - > colormod [ 0 ] = MSG_ReadByte ( ) ;
to - > colormod [ 1 ] = MSG_ReadByte ( ) ;
to - > colormod [ 2 ] = MSG_ReadByte ( ) ;
}
2009-11-04 21:16:50 +00:00
if ( morebits & U_ENTITYDBL & & cls . fteprotocolextensions & PEXT_ENTITYDBL )
2004-08-23 00:15:46 +00:00
to - > number + = 512 ;
2009-11-04 21:16:50 +00:00
if ( morebits & U_ENTITYDBL2 & & cls . fteprotocolextensions & PEXT_ENTITYDBL2 )
2004-08-23 00:15:46 +00:00
to - > number + = 1024 ;
2009-11-04 21:16:50 +00:00
if ( morebits & U_MODELDBL & & cls . fteprotocolextensions & PEXT_MODELDBL )
2004-08-23 00:15:46 +00:00
to - > modelindex + = 256 ;
2005-05-15 18:49:04 +00:00
if ( morebits & U_DPFLAGS ) // && cls.fteprotocolextensions & PEXT_DPFLAGS)
{
// these are bits for the 'flags' field of the entity_state_t
i = MSG_ReadByte ( ) ;
2009-07-18 20:46:42 +00:00
to - > dpflags = i ;
2005-05-15 18:49:04 +00:00
to - > flags = 0 ;
if ( i & RENDER_VIEWMODEL )
to - > flags | = Q2RF_WEAPONMODEL | Q2RF_MINLIGHT | Q2RF_DEPTHHACK ;
if ( i & RENDER_EXTERIORMODEL )
to - > flags | = Q2RF_EXTERNALMODEL ;
}
2005-07-01 19:23:00 +00:00
if ( morebits & U_TAGINFO )
{
to - > tagentity = MSG_ReadShort ( ) ;
to - > tagindex = MSG_ReadShort ( ) ;
}
2005-08-07 18:08:13 +00:00
if ( morebits & U_LIGHT )
{
to - > light [ 0 ] = MSG_ReadShort ( ) ;
to - > light [ 1 ] = MSG_ReadShort ( ) ;
to - > light [ 2 ] = MSG_ReadShort ( ) ;
to - > light [ 3 ] = MSG_ReadShort ( ) ;
to - > lightstyle = MSG_ReadByte ( ) ;
to - > lightpflags = MSG_ReadByte ( ) ;
}
2005-05-15 18:49:04 +00:00
2005-08-26 22:56:51 +00:00
if ( morebits & U_EFFECTS16 )
to - > effects = ( to - > effects & 0x00ff ) | ( MSG_ReadByte ( ) < < 8 ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
FlushEntityPacket
= = = = = = = = = = = = = = = = =
*/
void FlushEntityPacket ( void )
{
int word ;
entity_state_t olde , newe ;
Con_DPrintf ( " FlushEntityPacket \n " ) ;
memset ( & olde , 0 , sizeof ( olde ) ) ;
cl . validsequence = 0 ; // can't render a frame
cl . frames [ cls . netchan . incoming_sequence & UPDATE_MASK ] . invalid = true ;
// read it all, but ignore it
while ( 1 )
{
word = ( unsigned short ) MSG_ReadShort ( ) ;
if ( msg_badread )
{ // something didn't parse right...
Host_EndGame ( " msg_badread in packetentities " ) ;
return ;
}
if ( ! word )
break ; // done
CL_ParseDelta ( & olde , & newe , word , true ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
CL_ParsePacketEntities
An svc_packetentities has just been parsed , deal with the
rest of the data stream .
= = = = = = = = = = = = = = = = = =
*/
void CL_ParsePacketEntities ( qboolean delta )
{
int oldpacket , newpacket ;
packet_entities_t * oldp , * newp , dummy ;
int oldindex , newindex ;
int word , newnum , oldnum ;
qboolean full ;
2004-12-08 04:14:52 +00:00
int from ;
2005-11-30 01:20:53 +00:00
2009-11-04 21:16:50 +00:00
newpacket = cls . netchan . incoming_sequence & UPDATE_MASK ;
newp = & cl . frames [ newpacket ] . packet_entities ;
cl . frames [ newpacket ] . invalid = false ;
2010-03-14 14:35:56 +00:00
if ( cls . protocol = = CP_QUAKEWORLD & & cls . demoplayback = = DPB_MVD )
{
extern float nextdemotime , olddemotime , demtime ;
cl . oldgametime = cl . gametime ;
cl . oldgametimemark = cl . gametimemark ;
cl . gametime = nextdemotime ;
cl . gametimemark = realtime ;
newp - > servertime = cl . gametime ;
}
else if ( ! ( cls . fteprotocolextensions & PEXT_ACCURATETIMINGS ) & & cls . protocol = = CP_QUAKEWORLD )
2005-11-30 01:20:53 +00:00
{
cl . oldgametime = cl . gametime ;
cl . oldgametimemark = cl . gametimemark ;
cl . gametime = realtime ;
cl . gametimemark = realtime ;
2009-11-04 21:16:50 +00:00
newp - > servertime = realtime ;
}
else
newp - > servertime = cl . gametime ;
2005-11-26 03:02:55 +00:00
2004-08-23 00:15:46 +00:00
if ( delta )
{
from = MSG_ReadByte ( ) ;
2007-02-23 00:21:33 +00:00
// Con_Printf("%i %i from %i\n", cls.netchan.outgoing_sequence, cls.netchan.incoming_sequence, from);
2004-08-23 00:15:46 +00:00
oldpacket = cl . frames [ newpacket ] . delta_sequence ;
2008-01-09 00:52:31 +00:00
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
2004-08-23 00:15:46 +00:00
from = oldpacket = cls . netchan . incoming_sequence - 1 ;
2004-12-08 04:14:52 +00:00
if ( cls . netchan . outgoing_sequence - cls . netchan . incoming_sequence > = UPDATE_BACKUP - 1 ) {
// there are no valid frames left, so drop it
FlushEntityPacket ( ) ;
cl . validsequence = 0 ;
return ;
}
if ( ( from & UPDATE_MASK ) ! = ( oldpacket & UPDATE_MASK ) ) {
2004-08-23 00:15:46 +00:00
Con_DPrintf ( " WARNING: from mismatch \n " ) ;
2005-05-13 10:42:48 +00:00
// FlushEntityPacket ();
// cl.validsequence = 0;
// return;
2004-12-08 04:14:52 +00:00
}
2004-08-23 00:15:46 +00:00
2007-02-23 00:21:33 +00:00
if ( cls . netchan . outgoing_sequence - oldpacket > = UPDATE_BACKUP - 1 )
{
2004-12-08 04:14:52 +00:00
// we can't use this, it is too old
2004-08-23 00:15:46 +00:00
FlushEntityPacket ( ) ;
2004-12-08 04:14:52 +00:00
// don't clear cl.validsequence, so that frames can still be rendered;
// it is possible that a fresh packet will be received before
// (outgoing_sequence - incoming_sequence) exceeds UPDATE_BACKUP - 1
2004-08-23 00:15:46 +00:00
return ;
}
2004-12-08 04:14:52 +00:00
oldp = & cl . frames [ oldpacket & UPDATE_MASK ] . packet_entities ;
full = false ;
2004-08-23 00:15:46 +00:00
}
else
{ // this is a full update that we can start delta compressing from now
oldp = & dummy ;
dummy . num_entities = 0 ;
full = true ;
}
2004-12-08 04:14:52 +00:00
cl . oldvalidsequence = cl . validsequence ;
cl . validsequence = cls . netchan . incoming_sequence ;
2004-08-23 00:15:46 +00:00
oldindex = 0 ;
newindex = 0 ;
newp - > num_entities = 0 ;
while ( 1 )
{
word = ( unsigned short ) MSG_ReadShort ( ) ;
if ( msg_badread )
{ // something didn't parse right...
Host_EndGame ( " msg_badread in packetentities " ) ;
return ;
}
if ( ! word )
{
while ( oldindex < oldp - > num_entities )
{ // copy all the rest of the entities from the old packet
//Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
if ( newindex > = newp - > max_entities )
{
newp - > max_entities = newindex + 1 ;
2008-05-09 14:22:37 +00:00
newp - > entities = BZ_Realloc ( newp - > entities , sizeof ( entity_state_t ) * newp - > max_entities ) ;
2004-08-23 00:15:46 +00:00
}
if ( oldindex > = oldp - > max_entities )
Host_EndGame ( " Old packet entity too big \n " ) ;
newp - > entities [ newindex ] = oldp - > entities [ oldindex ] ;
newindex + + ;
oldindex + + ;
}
break ;
}
newnum = word & 511 ;
if ( word & U_MOREBITS )
{
int oldpos = msg_readcount ;
int excessive ;
excessive = MSG_ReadByte ( ) ;
if ( excessive & U_EVENMORE )
{
excessive = MSG_ReadByte ( ) ;
if ( excessive & U_ENTITYDBL )
newnum + = 512 ;
if ( excessive & U_ENTITYDBL2 )
newnum + = 1024 ;
2005-02-06 02:47:36 +00:00
}
2004-08-23 00:15:46 +00:00
msg_readcount = oldpos ; //undo the read...
}
oldnum = oldindex > = oldp - > num_entities ? 9999 : oldp - > entities [ oldindex ] . number ;
while ( newnum > oldnum )
{
if ( full )
{
Con_Printf ( " WARNING: oldcopy on full update " ) ;
FlushEntityPacket ( ) ;
return ;
}
//Con_Printf ("copy %i\n", oldnum);
// copy one of the old entities over to the new packet unchanged
if ( newindex > = newp - > max_entities )
{
newp - > max_entities = newindex + 1 ;
newp - > entities = BZ_Realloc ( newp - > entities , sizeof ( entity_state_t ) * newp - > max_entities ) ;
}
if ( oldindex > = oldp - > max_entities )
Host_EndGame ( " Old packet entity too big \n " ) ;
newp - > entities [ newindex ] = oldp - > entities [ oldindex ] ;
newindex + + ;
oldindex + + ;
oldnum = oldindex > = oldp - > num_entities ? 9999 : oldp - > entities [ oldindex ] . number ;
}
if ( newnum < oldnum )
{ // new from baseline
//Con_Printf ("baseline %i\n", newnum);
if ( word & U_REMOVE )
2005-10-20 00:04:57 +00:00
{ //really read the extra entity number if required
if ( word & U_MOREBITS )
if ( MSG_ReadByte ( ) & U_EVENMORE )
MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
if ( full )
{
cl . validsequence = 0 ;
Con_Printf ( " WARNING: U_REMOVE on full update \n " ) ;
FlushEntityPacket ( ) ;
return ;
}
continue ;
}
if ( newindex > = newp - > max_entities )
{
newp - > max_entities = newindex + 1 ;
newp - > entities = BZ_Realloc ( newp - > entities , sizeof ( entity_state_t ) * newp - > max_entities ) ;
}
2006-07-24 04:24:41 +00:00
if ( ! CL_CheckBaselines ( newnum ) )
Host_EndGame ( " CL_ParsePacketEntities: check baselines failed with size %i " , newnum ) ;
CL_ParseDelta ( cl_baselines + newnum , & newp - > entities [ newindex ] , word , true ) ;
2004-08-23 00:15:46 +00:00
newindex + + ;
continue ;
}
if ( newnum = = oldnum )
{ // delta from previous
if ( full )
{
cl . validsequence = 0 ;
Con_Printf ( " WARNING: delta on full update " ) ;
}
if ( word & U_REMOVE )
{
2005-10-20 00:04:57 +00:00
if ( word & U_MOREBITS )
if ( MSG_ReadByte ( ) & U_EVENMORE )
MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
oldindex + + ;
continue ;
}
if ( newindex > = newp - > max_entities )
{
newp - > max_entities = newindex + 1 ;
newp - > entities = BZ_Realloc ( newp - > entities , sizeof ( entity_state_t ) * newp - > max_entities ) ;
}
//Con_Printf ("delta %i\n",newnum);
CL_ParseDelta ( & oldp - > entities [ oldindex ] , & newp - > entities [ newindex ] , word , false ) ;
newindex + + ;
oldindex + + ;
}
}
newp - > num_entities = newindex ;
}
2004-11-29 01:21:00 +00:00
2004-08-23 00:15:46 +00:00
entity_state_t * CL_FindOldPacketEntity ( int num )
{
int pnum ;
entity_state_t * s1 ;
packet_entities_t * pack ;
2005-05-26 12:55:34 +00:00
if ( ! cl . validsequence )
2004-09-30 22:40:24 +00:00
return NULL ;
2005-06-04 04:20:20 +00:00
pack = & cl . frames [ ( cls . netchan . incoming_sequence - 1 ) & UPDATE_MASK ] . packet_entities ;
2004-08-23 00:15:46 +00:00
for ( pnum = 0 ; pnum < pack - > num_entities ; pnum + + )
{
s1 = & pack - > entities [ pnum ] ;
if ( num = = s1 - > number )
return s1 ;
}
return NULL ;
}
2004-11-29 01:21:00 +00:00
# ifdef NQPROT
2005-09-26 03:40:09 +00:00
2005-07-14 01:57:34 +00:00
entity_state_t defaultstate ;
2004-11-27 08:16:25 +00:00
void DP5_ParseDelta ( entity_state_t * s )
{
int bits ;
bits = MSG_ReadByte ( ) ;
if ( bits & E5_EXTEND1 )
{
bits | = MSG_ReadByte ( ) < < 8 ;
if ( bits & E5_EXTEND2 )
{
bits | = MSG_ReadByte ( ) < < 16 ;
if ( bits & E5_EXTEND3 )
bits | = MSG_ReadByte ( ) < < 24 ;
}
}
2005-09-26 03:40:09 +00:00
if ( bits & E5_ALLUNUSED )
{
Host_EndGame ( " Detected 'unused' bits in DP5+ entity delta - %x (%x) \n " , bits , ( bits & E5_ALLUNUSED ) ) ;
}
2004-11-27 08:16:25 +00:00
if ( bits & E5_FULLUPDATE )
{
2005-05-15 18:49:04 +00:00
int num ;
num = s - > number ;
2004-11-27 08:16:25 +00:00
* s = defaultstate ;
2005-07-14 01:57:34 +00:00
s - > trans = 255 ;
2005-08-26 22:56:51 +00:00
s - > scale = 16 ;
2005-05-15 18:49:04 +00:00
s - > number = num ;
2004-11-27 08:16:25 +00:00
// s->active = true;
}
if ( bits & E5_FLAGS )
2005-05-17 02:36:54 +00:00
{
int i = MSG_ReadByte ( ) ;
s - > flags = 0 ;
2007-12-15 18:51:34 +00:00
if ( i & RENDER_VIEWMODEL )
2005-05-17 02:36:54 +00:00
s - > flags | = Q2RF_WEAPONMODEL | Q2RF_MINLIGHT | Q2RF_DEPTHHACK ;
2007-12-15 18:51:34 +00:00
if ( i & RENDER_EXTERIORMODEL )
2005-05-17 02:36:54 +00:00
s - > flags | = Q2RF_EXTERNALMODEL ;
}
2004-11-27 08:16:25 +00:00
if ( bits & E5_ORIGIN )
{
if ( bits & E5_ORIGIN32 )
{
s - > origin [ 0 ] = MSG_ReadFloat ( ) ;
s - > origin [ 1 ] = MSG_ReadFloat ( ) ;
s - > origin [ 2 ] = MSG_ReadFloat ( ) ;
}
else
{
s - > origin [ 0 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
s - > origin [ 1 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
s - > origin [ 2 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
}
}
if ( bits & E5_ANGLES )
{
if ( bits & E5_ANGLES16 )
{
2005-02-06 02:47:36 +00:00
s - > angles [ 0 ] = MSG_ReadAngle16 ( ) ;
s - > angles [ 1 ] = MSG_ReadAngle16 ( ) ;
s - > angles [ 2 ] = MSG_ReadAngle16 ( ) ;
2004-11-27 08:16:25 +00:00
}
else
{
s - > angles [ 0 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
s - > angles [ 1 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
s - > angles [ 2 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
}
}
if ( bits & E5_MODEL )
{
if ( bits & E5_MODEL16 )
s - > modelindex = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > modelindex = MSG_ReadByte ( ) ;
}
if ( bits & E5_FRAME )
{
if ( bits & E5_FRAME16 )
s - > frame = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > frame = MSG_ReadByte ( ) ;
}
if ( bits & E5_SKIN )
s - > skinnum = MSG_ReadByte ( ) ;
if ( bits & E5_EFFECTS )
{
if ( bits & E5_EFFECTS32 )
s - > effects = ( unsigned int ) MSG_ReadLong ( ) ;
else if ( bits & E5_EFFECTS16 )
s - > effects = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > effects = MSG_ReadByte ( ) ;
}
if ( bits & E5_ALPHA )
2005-07-01 19:23:00 +00:00
s - > trans = MSG_ReadByte ( ) ;
2004-11-27 08:16:25 +00:00
if ( bits & E5_SCALE )
2005-07-01 19:23:00 +00:00
s - > scale = MSG_ReadByte ( ) ;
2004-11-27 08:16:25 +00:00
if ( bits & E5_COLORMAP )
s - > colormap = MSG_ReadByte ( ) ;
if ( bits & E5_ATTACHMENT )
{
2005-07-01 19:23:00 +00:00
s - > tagentity = MSG_ReadShort ( ) ;
s - > tagindex = MSG_ReadByte ( ) ;
2004-11-27 08:16:25 +00:00
}
if ( bits & E5_LIGHT )
{
2005-09-26 03:40:09 +00:00
s - > light [ 0 ] = MSG_ReadShort ( ) ;
s - > light [ 1 ] = MSG_ReadShort ( ) ;
s - > light [ 2 ] = MSG_ReadShort ( ) ;
s - > light [ 3 ] = MSG_ReadShort ( ) ;
s - > lightstyle = MSG_ReadByte ( ) ;
s - > lightpflags = MSG_ReadByte ( ) ;
2004-11-27 08:16:25 +00:00
}
if ( bits & E5_GLOW )
{
2005-05-19 02:53:03 +00:00
s - > glowsize = MSG_ReadByte ( ) ;
s - > glowcolour = MSG_ReadByte ( ) ;
2004-11-27 08:16:25 +00:00
}
2005-09-26 03:40:09 +00:00
if ( bits & E5_COLORMOD )
{
2006-02-27 00:42:25 +00:00
s - > colormod [ 0 ] = MSG_ReadByte ( ) ;
s - > colormod [ 1 ] = MSG_ReadByte ( ) ;
s - > colormod [ 2 ] = MSG_ReadByte ( ) ;
2005-09-26 03:40:09 +00:00
}
2004-11-27 08:16:25 +00:00
}
int cl_latestframenum ;
void CLNQ_ParseDarkPlaces5Entities ( void ) //the things I do.. :o(
{
//the incoming entities do not come in in any order. :(
//well, they come in in order of priorities, but that's not useful to us.
//I guess this means we'll have to go slowly.
packet_entities_t * pack , * oldpack ;
2005-02-06 02:47:36 +00:00
entity_state_t * to , * from ;
2004-11-27 08:16:25 +00:00
unsigned short read ;
int oldi ;
qboolean remove ;
cl_latestframenum = MSG_ReadLong ( ) ;
2005-05-26 12:55:34 +00:00
if ( nq_dp_protocol > = 7 )
2007-06-20 00:02:54 +00:00
cl . ackedinputsequence = MSG_ReadLong ( ) ;
2005-05-26 12:55:34 +00:00
2004-11-27 08:16:25 +00:00
pack = & cl . frames [ ( cls . netchan . incoming_sequence ) & UPDATE_MASK ] . packet_entities ;
2005-11-26 03:02:55 +00:00
pack - > servertime = cl . gametime ;
2004-11-27 08:16:25 +00:00
oldpack = & cl . frames [ ( cls . netchan . incoming_sequence - 1 ) & UPDATE_MASK ] . packet_entities ;
from = oldpack - > entities ;
oldi = 0 ;
pack - > num_entities = 0 ;
for ( oldi = 0 ; oldi < oldpack - > num_entities ; oldi + + )
{
from = & oldpack - > entities [ oldi ] ;
from - > flags & = ~ 0x80000000 ;
}
for ( read = MSG_ReadShort ( ) ; read ! = 0x8000 ; read = MSG_ReadShort ( ) )
{
if ( msg_badread )
Host_EndGame ( " Corrupt entitiy message packet \n " ) ;
remove = ! ! ( read & 0x8000 ) ;
read & = ~ 0x8000 ;
2005-08-26 22:56:51 +00:00
if ( read > = MAX_EDICTS )
Host_EndGame ( " Too many entities. \n " ) ;
2004-11-27 08:16:25 +00:00
from = & defaultstate ;
for ( oldi = 0 ; oldi < oldpack - > num_entities ; oldi + + )
{
if ( read = = oldpack - > entities [ oldi ] . number )
{
from = & oldpack - > entities [ oldi ] ;
2005-05-19 02:53:03 +00:00
from - > flags | = 0x80000000 ; //so we don't copy it.
2004-11-27 08:16:25 +00:00
break ;
}
}
if ( remove )
{
continue ;
}
if ( pack - > num_entities = = pack - > max_entities )
{
pack - > max_entities = pack - > num_entities + 16 ;
pack - > entities = BZ_Realloc ( pack - > entities , sizeof ( entity_state_t ) * pack - > max_entities ) ;
}
to = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
memcpy ( to , from , sizeof ( * to ) ) ;
to - > number = read ;
2005-05-15 18:49:04 +00:00
DP5_ParseDelta ( to ) ;
2005-05-19 02:53:03 +00:00
to - > flags & = ~ 0x80000000 ;
2004-11-27 08:16:25 +00:00
}
//the pack has all the new ones in it, now copy the old ones in that wern't removed (or changed).
for ( oldi = 0 ; oldi < oldpack - > num_entities ; oldi + + )
{
from = & oldpack - > entities [ oldi ] ;
if ( from - > flags & 0x80000000 )
continue ;
if ( pack - > num_entities = = pack - > max_entities )
{
pack - > max_entities = pack - > num_entities + 16 ;
pack - > entities = BZ_Realloc ( pack - > entities , sizeof ( entity_state_t ) * pack - > max_entities ) ;
}
to = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
from = & oldpack - > entities [ oldi ] ;
memcpy ( to , from , sizeof ( * to ) ) ;
}
}
2004-08-23 00:15:46 +00:00
2004-11-23 01:10:10 +00:00
void CLNQ_ParseEntity ( unsigned int bits )
2004-08-23 00:15:46 +00:00
{
int i ;
int num , pnum ;
2005-02-06 02:47:36 +00:00
entity_state_t * state , * from ;
2004-08-23 00:15:46 +00:00
entity_state_t * base ;
static float lasttime ;
packet_entities_t * pack ;
2004-11-23 01:10:10 +00:00
2004-08-23 00:15:46 +00:00
# define NQU_MOREBITS (1<<0)
# define NQU_ORIGIN1 (1<<1)
# define NQU_ORIGIN2 (1<<2)
# define NQU_ORIGIN3 (1<<3)
# define NQU_ANGLE2 (1<<4)
# define NQU_NOLERP (1<<5) // don't interpolate movement
# define NQU_FRAME (1<<6)
# define NQU_SIGNAL (1<<7) // just differentiates from other updates
// svc_update can pass all of the fast update bits, plus more
# define NQU_ANGLE1 (1<<8)
# define NQU_ANGLE3 (1<<9)
# define NQU_MODEL (1<<10)
# define NQU_COLORMAP (1<<11)
# define NQU_SKIN (1<<12)
# define NQU_EFFECTS (1<<13)
# define NQU_LONGENTITY (1<<14)
2005-02-06 02:47:36 +00:00
2004-11-23 01:10:10 +00:00
// LordHavoc's: protocol extension
# define DPU_EXTEND1 (1<<15)
// LordHavoc: first extend byte
# define DPU_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second)
# define DPU_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well)
# define DPU_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0
# define DPU_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte)
# define DPU_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0
# define DPU_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set)
// LordHavoc: colormod feature has been removed, because no one used it
# define DPU_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend...
# define DPU_EXTEND2 (1<<23) // another byte to follow
// LordHavoc: second extend byte
# define DPU_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize)
# define DPU_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such
# define DPU_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte)
# define DPU_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte)
# define DPU_EXTERIORMODEL (1<<28) // causes this model to not be drawn when using a first person view (third person will draw it, first person will not)
# define DPU_UNUSED29 (1<<29) // future expansion
# define DPU_UNUSED30 (1<<30) // future expansion
# define DPU_EXTEND3 (1<<31) // another byte to follow, future expansion
2004-08-23 00:15:46 +00:00
if ( cls . signon = = 4 - 1 )
{ // first update is the final signon stage
cls . signon = 4 ;
CLNQ_SignonReply ( ) ;
2005-02-06 02:47:36 +00:00
}
pack = & cl . frames [ cls . netchan . incoming_sequence & UPDATE_MASK ] . packet_entities ;
2004-08-23 00:15:46 +00:00
if ( bits & NQU_MOREBITS )
{
i = MSG_ReadByte ( ) ;
bits | = ( i < < 8 ) ;
}
2004-11-23 01:10:10 +00:00
if ( bits & DPU_EXTEND1 )
{
i = MSG_ReadByte ( ) ;
bits | = ( i < < 16 ) ;
}
if ( bits & DPU_EXTEND2 )
{
i = MSG_ReadByte ( ) ;
bits | = ( i < < 24 ) ;
}
2004-08-23 00:15:46 +00:00
2005-02-06 02:47:36 +00:00
if ( bits & NQU_LONGENTITY )
2004-08-23 00:15:46 +00:00
num = MSG_ReadShort ( ) ;
else
num = MSG_ReadByte ( ) ;
// state = CL_FindPacketEntity(num);
// if (!state)
{
// if ((int)(lasttime*100) != (int)(realtime*100))
// pack->num_entities=0;
// else
if ( pack - > num_entities = = pack - > max_entities )
{
pack - > max_entities = pack - > num_entities + 1 ;
pack - > entities = BZ_Realloc ( pack - > entities , sizeof ( entity_state_t ) * pack - > max_entities ) ;
2008-11-09 22:29:28 +00:00
memset ( pack - > entities + pack - > num_entities , 0 , sizeof ( entity_state_t ) ) ;
2004-08-23 00:15:46 +00:00
}
lasttime = realtime ;
state = & pack - > entities [ pack - > num_entities + + ] ;
}
2004-11-27 08:16:25 +00:00
from = CL_FindOldPacketEntity ( num ) ; //this could be optimised.
2004-08-23 00:15:46 +00:00
2006-07-24 04:24:41 +00:00
if ( ! CL_CheckBaselines ( num ) )
Host_EndGame ( " CLNQ_ParseEntity: check baselines failed with size %i " , num ) ;
base = cl_baselines + num ;
2004-08-23 00:15:46 +00:00
state - > number = num ;
2005-02-06 02:47:36 +00:00
if ( bits & NQU_MODEL )
2004-08-23 00:15:46 +00:00
state - > modelindex = MSG_ReadByte ( ) ;
else
state - > modelindex = base - > modelindex ;
if ( bits & NQU_FRAME )
state - > frame = MSG_ReadByte ( ) ;
else
state - > frame = base - > frame ;
if ( bits & NQU_COLORMAP )
state - > colormap = MSG_ReadByte ( ) ;
else
2009-02-03 00:08:32 +00:00
state - > colormap = base - > colormap ;
2004-08-23 00:15:46 +00:00
if ( bits & NQU_SKIN )
state - > skinnum = MSG_ReadByte ( ) ;
else
state - > skinnum = base - > skinnum ;
if ( bits & NQU_EFFECTS )
state - > effects = MSG_ReadByte ( ) ;
else
state - > effects = base - > effects ;
if ( bits & NQU_ORIGIN1 )
state - > origin [ 0 ] = MSG_ReadCoord ( ) ;
else
state - > origin [ 0 ] = base - > origin [ 0 ] ;
if ( bits & NQU_ANGLE1 )
state - > angles [ 0 ] = MSG_ReadAngle ( ) ;
else
state - > angles [ 0 ] = base - > angles [ 0 ] ;
if ( bits & NQU_ORIGIN2 )
state - > origin [ 1 ] = MSG_ReadCoord ( ) ;
else
state - > origin [ 1 ] = base - > origin [ 1 ] ;
if ( bits & NQU_ANGLE2 )
state - > angles [ 1 ] = MSG_ReadAngle ( ) ;
else
state - > angles [ 1 ] = base - > angles [ 1 ] ;
if ( bits & NQU_ORIGIN3 )
state - > origin [ 2 ] = MSG_ReadCoord ( ) ;
else
state - > origin [ 2 ] = base - > origin [ 2 ] ;
if ( bits & NQU_ANGLE3 )
state - > angles [ 2 ] = MSG_ReadAngle ( ) ;
else
state - > angles [ 2 ] = base - > angles [ 2 ] ;
2006-06-09 00:58:11 +00:00
if ( bits & DPU_ALPHA )
i = MSG_ReadByte ( ) ;
else
i = - 1 ;
2005-08-12 01:37:27 +00:00
# ifdef PEXT_TRANS
2006-06-09 00:58:11 +00:00
if ( i = = - 1 )
state - > trans = base - > trans ;
else
state - > trans = i ;
# endif
if ( bits & DPU_SCALE )
i = MSG_ReadByte ( ) ;
else
i = - 1 ;
# ifdef PEXT_SCALE
if ( i = = - 1 )
state - > scale = base - > scale ;
else
state - > scale = i ;
2005-08-12 01:37:27 +00:00
# endif
2006-06-09 00:58:11 +00:00
if ( bits & DPU_EFFECTS2 )
state - > effects | = MSG_ReadByte ( ) < < 8 ;
if ( bits & DPU_GLOWSIZE )
state - > glowsize = MSG_ReadByte ( ) ;
else
state - > glowsize = base - > glowsize ;
if ( bits & DPU_GLOWCOLOR )
state - > glowcolour = MSG_ReadByte ( ) ;
else
state - > glowcolour = base - > glowcolour ;
if ( bits & DPU_COLORMOD )
{
i = MSG_ReadByte ( ) ; // follows format RRRGGGBB
state - > colormod [ 0 ] = ( qbyte ) ( ( ( i > > 5 ) & 7 ) * ( 32.0f / 7.0f ) ) ;
state - > colormod [ 1 ] = ( qbyte ) ( ( ( i > > 2 ) & 7 ) * ( 32.0f / 7.0f ) ) ;
state - > colormod [ 2 ] = ( qbyte ) ( ( i & 3 ) * ( 32.0f / 3.0f ) ) ;
}
else
{
state - > colormod [ 0 ] = base - > colormod [ 0 ] ;
state - > colormod [ 1 ] = base - > colormod [ 1 ] ;
state - > colormod [ 2 ] = base - > colormod [ 2 ] ;
}
if ( bits & DPU_FRAME2 )
state - > frame | = MSG_ReadByte ( ) < < 8 ;
if ( bits & DPU_MODEL2 )
state - > modelindex | = MSG_ReadByte ( ) < < 8 ;
2004-08-23 00:15:46 +00:00
if ( cls . demoplayback ! = DPB_NONE )
for ( pnum = 0 ; pnum < cl . splitclients ; pnum + + )
if ( num = = cl . viewentity [ pnum ] )
{
state - > angles [ 0 ] = cl . viewangles [ pnum ] [ 0 ] / - 3 ;
state - > angles [ 1 ] = cl . viewangles [ pnum ] [ 1 ] ;
state - > angles [ 2 ] = cl . viewangles [ pnum ] [ 2 ] ;
}
}
# endif
# ifdef PEXT_SETVIEW
entity_state_t * CL_FindPacketEntity ( int num )
{
int pnum ;
entity_state_t * s1 ;
packet_entities_t * pack ;
pack = & cl . frames [ cls . netchan . incoming_sequence & UPDATE_MASK ] . packet_entities ;
for ( pnum = 0 ; pnum < pack - > num_entities ; pnum + + )
{
s1 = & pack - > entities [ pnum ] ;
if ( num = = s1 - > number )
return s1 ;
}
return NULL ;
}
# endif
2009-07-18 20:46:42 +00:00
void CL_RotateAroundTag ( entity_t * ent , int entnum , int parenttagent , int parenttagnum )
2004-10-10 06:32:29 +00:00
{
entity_state_t * ps ;
float * org = NULL , * ang = NULL ;
2004-11-17 17:55:19 +00:00
vec3_t axis [ 3 ] ;
2005-06-14 04:52:10 +00:00
float transform [ 12 ] , parent [ 12 ] , result [ 12 ] , old [ 12 ] , temp [ 12 ] ;
2004-11-17 17:55:19 +00:00
2008-12-23 02:55:20 +00:00
int model ;
framestate_t fstate ;
2004-10-10 06:32:29 +00:00
2009-07-18 20:46:42 +00:00
if ( parenttagent > cl . maxlerpents )
2008-11-09 22:29:28 +00:00
{
Con_Printf ( " tag entity out of range! \n " ) ;
return ;
}
2008-12-23 02:55:20 +00:00
memset ( & fstate , 0 , sizeof ( fstate ) ) ;
2009-07-18 20:46:42 +00:00
//for visibility checks
ent - > keynum = parenttagent ;
2005-02-28 07:16:19 +00:00
2009-07-18 20:46:42 +00:00
ps = CL_FindPacketEntity ( parenttagent ) ;
2004-10-10 06:32:29 +00:00
if ( ps )
{
2005-07-01 19:23:00 +00:00
if ( ps - > tagentity )
2009-07-18 20:46:42 +00:00
CL_RotateAroundTag ( ent , entnum , ps - > tagentity , ps - > tagindex ) ;
2005-07-01 19:23:00 +00:00
2004-10-10 06:32:29 +00:00
org = ps - > origin ;
ang = ps - > angles ;
2004-11-17 17:55:19 +00:00
model = ps - > modelindex ;
2009-07-18 20:46:42 +00:00
CL_LerpNetFrameState ( FS_REG , & fstate , & cl . lerpents [ parenttagent ] ) ;
2004-10-10 06:32:29 +00:00
}
else
{
extern int parsecountmod ;
2005-02-06 02:47:36 +00:00
// Con_Printf("tagent %i\n", tagent);
2009-07-18 20:46:42 +00:00
if ( parenttagent < = MAX_CLIENTS & & parenttagent > 0 )
2004-10-10 06:32:29 +00:00
{
2009-07-18 20:46:42 +00:00
if ( parenttagent = = cl . playernum [ 0 ] + 1 )
2004-10-10 06:32:29 +00:00
{
org = cl . simorg [ 0 ] ;
ang = cl . simangles [ 0 ] ;
}
else
{
2009-07-18 20:46:42 +00:00
org = cl . frames [ parsecountmod ] . playerstate [ parenttagent - 1 ] . origin ;
ang = cl . frames [ parsecountmod ] . playerstate [ parenttagent - 1 ] . viewangles ;
2004-10-10 06:32:29 +00:00
}
2009-07-18 20:46:42 +00:00
model = cl . frames [ parsecountmod ] . playerstate [ parenttagent - 1 ] . modelindex ;
CL_LerpNetFrameState ( FS_REG , & fstate , & cl . lerpplayers [ parenttagent - 1 ] ) ;
2004-10-10 06:32:29 +00:00
}
2009-02-03 00:08:32 +00:00
else
2009-07-18 20:46:42 +00:00
{
CL_LerpNetFrameState ( FS_REG , & fstate , & cl . lerpents [ parenttagent ] ) ;
2009-02-03 00:08:32 +00:00
model = 0 ;
2009-07-18 20:46:42 +00:00
}
2004-10-10 06:32:29 +00:00
}
if ( ang )
{
2006-02-01 22:36:12 +00:00
ang [ 0 ] * = - 1 ;
2004-11-17 17:55:19 +00:00
AngleVectors ( ang , axis [ 0 ] , axis [ 1 ] , axis [ 2 ] ) ;
2006-02-01 22:36:12 +00:00
ang [ 0 ] * = - 1 ;
2004-11-17 17:55:19 +00:00
VectorInverse ( axis [ 1 ] ) ;
2009-07-18 20:46:42 +00:00
// fstate.g[FS_REG].lerpfrac = CL_EntLerpFactor(tagent);
// fstate.g[FS_REG].frametime[0] = cl.time - cl.lerpents[tagent].framechange;
// fstate.g[FS_REG].frametime[1] = cl.time - cl.lerpents[tagent].oldframechange;
if ( Mod_GetTag ( cl . model_precache [ model ] , parenttagnum , & fstate , transform ) )
2004-11-17 17:55:19 +00:00
{
2005-06-14 04:52:10 +00:00
old [ 0 ] = ent - > axis [ 0 ] [ 0 ] ;
old [ 1 ] = ent - > axis [ 1 ] [ 0 ] ;
old [ 2 ] = ent - > axis [ 2 ] [ 0 ] ;
old [ 3 ] = ent - > origin [ 0 ] ;
old [ 4 ] = ent - > axis [ 0 ] [ 1 ] ;
old [ 5 ] = ent - > axis [ 1 ] [ 1 ] ;
old [ 6 ] = ent - > axis [ 2 ] [ 1 ] ;
old [ 7 ] = ent - > origin [ 1 ] ;
old [ 8 ] = ent - > axis [ 0 ] [ 2 ] ;
old [ 9 ] = ent - > axis [ 1 ] [ 2 ] ;
old [ 10 ] = ent - > axis [ 2 ] [ 2 ] ;
old [ 11 ] = ent - > origin [ 2 ] ;
parent [ 0 ] = axis [ 0 ] [ 0 ] ;
parent [ 1 ] = axis [ 1 ] [ 0 ] ;
parent [ 2 ] = axis [ 2 ] [ 0 ] ;
parent [ 3 ] = org [ 0 ] ;
parent [ 4 ] = axis [ 0 ] [ 1 ] ;
parent [ 5 ] = axis [ 1 ] [ 1 ] ;
parent [ 6 ] = axis [ 2 ] [ 1 ] ;
parent [ 7 ] = org [ 1 ] ;
parent [ 8 ] = axis [ 0 ] [ 2 ] ;
parent [ 9 ] = axis [ 1 ] [ 2 ] ;
parent [ 10 ] = axis [ 2 ] [ 2 ] ;
parent [ 11 ] = org [ 2 ] ;
R_ConcatTransforms ( ( void * ) old , ( void * ) parent , ( void * ) temp ) ;
R_ConcatTransforms ( ( void * ) temp , ( void * ) transform , ( void * ) result ) ;
ent - > axis [ 0 ] [ 0 ] = result [ 0 ] ;
ent - > axis [ 1 ] [ 0 ] = result [ 1 ] ;
ent - > axis [ 2 ] [ 0 ] = result [ 2 ] ;
ent - > origin [ 0 ] = result [ 3 ] ;
ent - > axis [ 0 ] [ 1 ] = result [ 4 ] ;
ent - > axis [ 1 ] [ 1 ] = result [ 5 ] ;
ent - > axis [ 2 ] [ 1 ] = result [ 6 ] ;
ent - > origin [ 1 ] = result [ 7 ] ;
ent - > axis [ 0 ] [ 2 ] = result [ 8 ] ;
ent - > axis [ 1 ] [ 2 ] = result [ 9 ] ;
ent - > axis [ 2 ] [ 2 ] = result [ 10 ] ;
ent - > origin [ 2 ] = result [ 11 ] ;
2004-11-17 17:55:19 +00:00
}
else //hrm.
2005-02-06 02:47:36 +00:00
{
2006-02-01 22:36:12 +00:00
old [ 0 ] = ent - > axis [ 0 ] [ 0 ] ;
old [ 1 ] = ent - > axis [ 1 ] [ 0 ] ;
old [ 2 ] = ent - > axis [ 2 ] [ 0 ] ;
old [ 3 ] = ent - > origin [ 0 ] ;
old [ 4 ] = ent - > axis [ 0 ] [ 1 ] ;
old [ 5 ] = ent - > axis [ 1 ] [ 1 ] ;
old [ 6 ] = ent - > axis [ 2 ] [ 1 ] ;
old [ 7 ] = ent - > origin [ 1 ] ;
old [ 8 ] = ent - > axis [ 0 ] [ 2 ] ;
old [ 9 ] = ent - > axis [ 1 ] [ 2 ] ;
old [ 10 ] = ent - > axis [ 2 ] [ 2 ] ;
old [ 11 ] = ent - > origin [ 2 ] ;
parent [ 0 ] = axis [ 0 ] [ 0 ] ;
parent [ 1 ] = axis [ 1 ] [ 0 ] ;
parent [ 2 ] = axis [ 2 ] [ 0 ] ;
parent [ 3 ] = org [ 0 ] ;
parent [ 4 ] = axis [ 0 ] [ 1 ] ;
parent [ 5 ] = axis [ 1 ] [ 1 ] ;
parent [ 6 ] = axis [ 2 ] [ 1 ] ;
parent [ 7 ] = org [ 1 ] ;
parent [ 8 ] = axis [ 0 ] [ 2 ] ;
parent [ 9 ] = axis [ 1 ] [ 2 ] ;
parent [ 10 ] = axis [ 2 ] [ 2 ] ;
parent [ 11 ] = org [ 2 ] ;
R_ConcatTransforms ( ( void * ) old , ( void * ) parent , ( void * ) result ) ;
ent - > axis [ 0 ] [ 0 ] = result [ 0 ] ;
ent - > axis [ 1 ] [ 0 ] = result [ 1 ] ;
ent - > axis [ 2 ] [ 0 ] = result [ 2 ] ;
ent - > origin [ 0 ] = result [ 3 ] ;
ent - > axis [ 0 ] [ 1 ] = result [ 4 ] ;
ent - > axis [ 1 ] [ 1 ] = result [ 5 ] ;
ent - > axis [ 2 ] [ 1 ] = result [ 6 ] ;
ent - > origin [ 1 ] = result [ 7 ] ;
ent - > axis [ 0 ] [ 2 ] = result [ 8 ] ;
ent - > axis [ 1 ] [ 2 ] = result [ 9 ] ;
ent - > axis [ 2 ] [ 2 ] = result [ 10 ] ;
ent - > origin [ 2 ] = result [ 11 ] ;
2005-02-06 02:47:36 +00:00
}
2004-10-10 06:32:29 +00:00
}
}
2005-02-28 07:16:19 +00:00
2005-08-03 23:14:59 +00:00
void V_AddAxisEntity ( entity_t * in )
{
entity_t * ent ;
if ( cl_numvisedicts = = MAX_VISEDICTS )
{
Con_Printf ( " Visedict list is full! \n " ) ;
return ; // object list is full
}
ent = & cl_visedicts [ cl_numvisedicts ] ;
cl_numvisedicts + + ;
* ent = * in ;
}
2005-02-28 07:16:19 +00:00
void V_AddEntity ( entity_t * in )
{
entity_t * ent ;
2005-06-04 04:20:20 +00:00
2005-02-28 07:16:19 +00:00
if ( cl_numvisedicts = = MAX_VISEDICTS )
2005-06-04 04:20:20 +00:00
{
Con_Printf ( " Visedict list is full! \n " ) ;
2005-02-28 07:16:19 +00:00
return ; // object list is full
2005-06-04 04:20:20 +00:00
}
2005-02-28 07:16:19 +00:00
ent = & cl_visedicts [ cl_numvisedicts ] ;
cl_numvisedicts + + ;
* ent = * in ;
ent - > angles [ 0 ] * = - 1 ;
AngleVectors ( ent - > angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
ent - > angles [ 0 ] * = - 1 ;
}
2008-12-23 02:55:20 +00:00
void VQ2_AddLerpEntity ( entity_t * in ) //a convienience function
2005-03-18 06:14:07 +00:00
{
entity_t * ent ;
float fwds , back ;
int i ;
if ( cl_numvisedicts = = MAX_VISEDICTS )
return ; // object list is full
ent = & cl_visedicts [ cl_numvisedicts ] ;
cl_numvisedicts + + ;
* ent = * in ;
2008-12-23 02:55:20 +00:00
fwds = ent - > framestate . g [ FS_REG ] . lerpfrac ;
back = 1 - ent - > framestate . g [ FS_REG ] . lerpfrac ;
2005-03-18 06:14:07 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
ent - > origin [ i ] = in - > origin [ i ] * fwds + in - > oldorigin [ i ] * back ;
}
2008-12-23 02:55:20 +00:00
ent - > framestate . g [ FS_REG ] . lerpfrac = back ;
2005-05-15 18:49:04 +00:00
2005-03-18 06:14:07 +00:00
ent - > angles [ 0 ] * = - 1 ;
AngleVectors ( ent - > angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
ent - > angles [ 0 ] * = - 1 ;
}
2009-11-04 21:16:50 +00:00
int V_AddLight ( int entsource , vec3_t org , float quant , float r , float g , float b )
2007-05-25 22:16:29 +00:00
{
2009-11-04 21:16:50 +00:00
return CL_NewDlightRGB ( entsource , org , quant , - 0.1 , r , g , b ) - cl_dlights ;
2007-05-25 22:16:29 +00:00
}
2009-07-18 20:46:42 +00:00
static void CL_LerpNetFrameState ( int fsanim , framestate_t * fs , lerpents_t * le )
{
fs - > g [ fsanim ] . frame [ 0 ] = le - > newframe ;
fs - > g [ fsanim ] . frame [ 1 ] = le - > oldframe ;
fs - > g [ fsanim ] . frametime [ 0 ] = cl . servertime - le - > newframestarttime ;
fs - > g [ fsanim ] . frametime [ 1 ] = cl . servertime - le - > oldframestarttime ;
fs - > g [ fsanim ] . lerpfrac = 1 - ( fs - > g [ fsanim ] . frametime [ 0 ] ) / le - > framelerpdeltatime ;
fs - > g [ fsanim ] . lerpfrac = bound ( 0 , fs - > g [ FS_REG ] . lerpfrac , 1 ) ;
}
2010-03-14 14:35:56 +00:00
static void CL_UpdateNetFrameLerpState ( qboolean force , unsigned int curframe , lerpents_t * le )
2009-07-18 20:46:42 +00:00
{
if ( force | | curframe ! = le - > newframe )
{
le - > framelerpdeltatime = bound ( 0 , cl . servertime - le - > newframestarttime , 0.1 ) ; //clamp to 10 tics per second
if ( ! force )
{
le - > oldframe = le - > newframe ;
le - > oldframestarttime = le - > newframestarttime ;
}
else
{
le - > oldframe = curframe ;
le - > oldframestarttime = cl . servertime ;
}
le - > newframe = curframe ;
le - > newframestarttime = cl . servertime ;
}
}
2010-07-11 02:22:39 +00:00
void CL_LinkStaticEntities ( void * pvs )
{
int i ;
entity_t * ent , * stat ;
model_t * clmodel ;
extern cvar_t r_drawflame , gl_part_flame ;
// if (!cl_staticentities.ival)
// return;
if ( ! cl . worldmodel )
return ;
for ( i = 0 ; i < cl . num_statics ; i + + )
{
if ( cl_numvisedicts = = MAX_VISEDICTS )
break ;
stat = & cl_static_entities [ i ] . ent ;
clmodel = stat - > model ;
if ( ( ! r_drawflame . ival ) & & ( clmodel - > engineflags & MDLF_FLAME ) )
continue ;
if ( ! cl . worldmodel - > funcs . EdictInFatPVS ( cl . worldmodel , & cl_static_entities [ i ] . pvscache , pvs ) )
continue ;
/*pvs test*/
ent = & cl_visedicts [ cl_numvisedicts + + ] ;
* ent = * stat ;
ent - > framestate . g [ FS_REG ] . frametime [ 0 ] = cl . time ;
ent - > framestate . g [ FS_REG ] . frametime [ 1 ] = cl . time ;
// emit particles for statics (we don't need to cheat check statics)
if ( clmodel - > particleeffect > = 0 & & gl_part_flame . ival )
{
// TODO: this is ugly.. assumes ent is in static entities, and subtracts
// pointer math to get an index to use in cl_static emit
// there needs to be a cleaner method for this
P_EmitEffect ( ent - > origin , clmodel - > particleeffect , & cl_static_entities [ i ] . emit ) ;
}
}
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = =
CL_LinkPacketEntities
= = = = = = = = = = = = = = =
*/
void R_FlameTrail ( vec3_t start , vec3_t end , float seperation ) ;
2005-11-26 03:02:55 +00:00
2010-03-14 14:35:56 +00:00
/*
Interpolates the two packets by the given time , writes its results into the lerpentities array .
*/
static void CL_TransitionPacketEntities ( packet_entities_t * newpack , packet_entities_t * oldpack , float servertime )
2005-11-26 03:02:55 +00:00
{
lerpents_t * le ;
entity_state_t * snew , * sold ;
int i , j ;
int oldpnum , newpnum ;
vec3_t move ;
float a1 , a2 ;
float frac ;
/*
seeing as how dropped packets cannot be filled in due to the reliable networking stuff ,
We can simply detect changes and lerp towards them
*/
//we have two index-sorted lists of entities
//we figure out which ones are new,
//we don't care about old, as our caller will use the lerpents array we fill, and the entity numbers from the 'new' packet.
if ( newpack - > servertime = = oldpack - > servertime )
frac = 1 ; //lerp totally into the new
else
frac = ( servertime - oldpack - > servertime ) / ( newpack - > servertime - oldpack - > servertime ) ;
oldpnum = 0 ;
for ( newpnum = 0 ; newpnum < newpack - > num_entities ; newpnum + + )
{
snew = & newpack - > entities [ newpnum ] ;
sold = NULL ;
for ( ; oldpnum < oldpack - > num_entities ; oldpnum + + )
{
sold = & oldpack - > entities [ oldpnum ] ;
if ( sold - > number > = snew - > number )
{
if ( sold - > number > snew - > number )
sold = NULL ; //woo, it's a new entity.
break ;
}
}
if ( ! sold ) //I'm lazy
sold = snew ;
if ( snew - > number > = cl . maxlerpents )
{
2008-05-09 14:22:37 +00:00
int newmaxle = snew - > number + 16 ;
cl . lerpents = BZ_Realloc ( cl . lerpents , newmaxle * sizeof ( lerpents_t ) ) ;
memset ( cl . lerpents + cl . maxlerpents , 0 , sizeof ( lerpents_t ) * ( newmaxle - cl . maxlerpents ) ) ;
cl . maxlerpents = newmaxle ;
2005-11-26 03:02:55 +00:00
}
le = & cl . lerpents [ snew - > number ] ;
2009-03-03 01:52:30 +00:00
VectorSubtract ( snew - > origin , sold - > origin , move ) ;
2005-11-26 03:02:55 +00:00
if ( DotProduct ( move , move ) > 200 * 200 | | snew - > modelindex ! = sold - > modelindex )
{
sold = snew ; //teleported?
VectorClear ( move ) ;
}
2009-07-18 20:46:42 +00:00
if ( sold = = snew )
2005-11-26 03:02:55 +00:00
{
2009-07-18 20:46:42 +00:00
//new this frame (or we noticed something changed significantly)
VectorCopy ( snew - > origin , le - > origin ) ;
VectorCopy ( snew - > angles , le - > angles ) ;
2005-11-26 03:02:55 +00:00
2009-07-18 20:46:42 +00:00
le - > orglerpdeltatime = 0.1 ;
le - > orglerpstarttime = oldpack - > servertime ;
}
else if ( snew - > dpflags & RENDER_STEP )
{
float lfrac ;
//ignore the old packet entirely, except for maybe its time.
if ( ! VectorEquals ( le - > neworigin , snew - > origin ) | | ! VectorEquals ( le - > newangle , snew - > angles ) )
2005-11-26 03:02:55 +00:00
{
2009-07-18 20:46:42 +00:00
le - > orglerpdeltatime = bound ( 0 , oldpack - > servertime - le - > orglerpstarttime , 0.1 ) ; //clamp to 10 tics per second
le - > orglerpstarttime = oldpack - > servertime ;
VectorCopy ( le - > neworigin , le - > oldorigin ) ;
VectorCopy ( le - > newangle , le - > oldangle ) ;
VectorCopy ( snew - > origin , le - > neworigin ) ;
VectorCopy ( snew - > angles , le - > newangle ) ;
2005-11-26 03:02:55 +00:00
}
2009-07-18 20:46:42 +00:00
lfrac = ( servertime - le - > orglerpstarttime ) / le - > orglerpdeltatime ;
lfrac = bound ( 0 , lfrac , 1 ) ;
for ( i = 0 ; i < 3 ; i + + )
{
le - > origin [ i ] = le - > oldorigin [ i ] + lfrac * ( le - > neworigin [ i ] - le - > oldorigin [ i ] ) ;
2005-11-26 03:02:55 +00:00
2009-07-18 20:46:42 +00:00
for ( j = 0 ; j < 3 ; j + + )
{
a1 = le - > oldangle [ i ] ;
a2 = le - > newangle [ i ] ;
if ( a1 - a2 > 180 )
a1 - = 360 ;
if ( a1 - a2 < - 180 )
a1 + = 360 ;
le - > angles [ i ] = a1 + lfrac * ( a2 - a1 ) ;
}
}
}
else
{
//lerp based purely on the packet times,
for ( i = 0 ; i < 3 ; i + + )
{
le - > origin [ i ] = sold - > origin [ i ] + frac * ( move [ i ] ) ;
2009-07-05 18:45:53 +00:00
2009-07-18 20:46:42 +00:00
for ( j = 0 ; j < 3 ; j + + )
{
a1 = sold - > angles [ i ] ;
a2 = snew - > angles [ i ] ;
if ( a1 - a2 > 180 )
a1 - = 360 ;
if ( a1 - a2 < - 180 )
a1 + = 360 ;
le - > angles [ i ] = a1 + frac * ( a2 - a1 ) ;
}
}
le - > orglerpdeltatime = 0.1 ;
le - > orglerpstarttime = oldpack - > servertime ;
2005-11-26 03:02:55 +00:00
}
2009-07-18 20:46:42 +00:00
CL_UpdateNetFrameLerpState ( sold = = snew , snew - > frame , le ) ;
2005-11-26 03:02:55 +00:00
}
}
2010-03-14 14:35:56 +00:00
static qboolean CL_ChooseInterpolationFrames ( int * newf , int * oldf , float servertime )
2005-11-26 03:02:55 +00:00
{
2010-03-14 14:35:56 +00:00
int i ;
float newtime = 0 ;
* oldf = - 1 ;
* newf = - 1 ;
2005-11-26 03:02:55 +00:00
//choose the two packets.
//we should be picking the packet just after the server time, and the one just before
for ( i = cls . netchan . incoming_sequence ; i > = cls . netchan . incoming_sequence - UPDATE_MASK ; i - - )
{
if ( cl . frames [ i & UPDATE_MASK ] . receivedtime < 0 | | cl . frames [ i & UPDATE_MASK ] . invalid )
continue ; //packetloss/choke, it's really only a problem for the oldframe, but...
2010-03-14 14:35:56 +00:00
if ( cl . frames [ i & UPDATE_MASK ] . packet_entities . servertime > = servertime )
2005-11-26 03:02:55 +00:00
{
if ( cl . frames [ i & UPDATE_MASK ] . packet_entities . servertime )
{
2010-03-14 14:35:56 +00:00
if ( ! newtime | | newtime ! = cl . frames [ i & UPDATE_MASK ] . packet_entities . servertime ) //if it's a duplicate, pick the latest (so just-shot rockets are still present)
{
newtime = cl . frames [ i & UPDATE_MASK ] . packet_entities . servertime ;
* newf = i ;
}
2005-11-26 03:02:55 +00:00
}
}
2010-03-14 14:35:56 +00:00
else if ( newtime )
2005-11-26 03:02:55 +00:00
{
2010-03-14 14:35:56 +00:00
if ( cl . frames [ i & UPDATE_MASK ] . packet_entities . servertime ! = newtime )
2005-11-26 03:02:55 +00:00
{ //it does actually lerp, and isn't an identical frame.
2010-03-14 14:35:56 +00:00
* oldf = i ;
2005-11-26 03:02:55 +00:00
break ;
}
}
}
2010-03-14 14:35:56 +00:00
if ( * newf = = - 1 )
2005-11-26 03:02:55 +00:00
{
2010-03-14 14:35:56 +00:00
/*
This can happen if the client ' s predicted time is greater than the most recently received packet .
This should of course not happen . . .
*/
2005-11-26 03:02:55 +00:00
Con_DPrintf ( " Warning: No lerp-to frame packet \n " ) ;
2010-03-14 14:35:56 +00:00
/*just grab the most recent frame that is valid*/
for ( i = cls . netchan . incoming_sequence ; i > = cls . netchan . incoming_sequence - UPDATE_MASK ; i - - )
{
if ( cl . frames [ i & UPDATE_MASK ] . receivedtime < 0 | | cl . frames [ i & UPDATE_MASK ] . invalid )
continue ; //packetloss/choke, it's really only a problem for the oldframe, but...
* oldf = * newf = i ;
return true ;
}
return false ;
2005-11-26 03:02:55 +00:00
}
2010-03-14 14:35:56 +00:00
else if ( * oldf = = - 1 ) //can happen at map start, and really laggy games, but really shouldn't in a normal game
2005-11-26 03:02:55 +00:00
{
2010-03-14 14:35:56 +00:00
* oldf = * newf ;
}
return true ;
}
/*obtains the current entity frame, and invokes CL_TransitionPacketEntities to process the interpolation details
*/
static packet_entities_t * CL_ProcessPacketEntities ( float * servertime , qboolean nolerp )
{
packet_entities_t * packnew , * packold ;
int newf , oldf ;
if ( nolerp )
{ //force our emulated time to as late as we can.
//this will disable all position interpolation
* servertime = cl . frames [ cls . netchan . incoming_sequence & UPDATE_MASK ] . packet_entities . servertime ;
2005-11-26 03:02:55 +00:00
}
2010-03-14 14:35:56 +00:00
if ( ! CL_ChooseInterpolationFrames ( & newf , & oldf , * servertime ) )
return NULL ;
2005-11-26 03:02:55 +00:00
2010-03-14 14:35:56 +00:00
packnew = & cl . frames [ newf & UPDATE_MASK ] . packet_entities ;
packold = & cl . frames [ oldf & UPDATE_MASK ] . packet_entities ;
2005-11-26 03:02:55 +00:00
2010-03-14 14:35:56 +00:00
CL_TransitionPacketEntities ( packnew , packold , * servertime ) ;
2005-11-26 03:02:55 +00:00
return packnew ;
}
2008-12-03 02:42:05 +00:00
qboolean CL_MayLerp ( void )
{
//force lerping when playing low-framerate demos.
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
return true ;
# ifdef NQPROT
if ( cls . demoplayback = = DPB_NETQUAKE )
return true ;
if ( cls . protocol = = CP_NETQUAKE ) //this includes DP protocols.
2010-07-11 02:22:39 +00:00
return ! cl_nolerp_netquake . ival ;
2008-12-03 02:42:05 +00:00
# endif
2010-07-11 02:22:39 +00:00
if ( cl_nolerp . ival = = 2 & & cls . gamemode ! = GAME_DEATHMATCH )
return true ;
return ! cl_nolerp . ival ;
2008-12-03 02:42:05 +00:00
}
2005-11-26 03:02:55 +00:00
void CL_LinkPacketEntities ( void )
{
entity_t * ent ;
packet_entities_t * pack ;
entity_state_t * state ;
lerpents_t * le ;
model_t * model ;
vec3_t old_origin ;
float autorotate ;
int i ;
2005-11-30 01:20:53 +00:00
int newpnum ;
2005-11-26 03:02:55 +00:00
//, spnum;
dlight_t * dl ;
vec3_t angles ;
2008-01-16 06:36:24 +00:00
qboolean nolerp ;
2005-11-26 03:02:55 +00:00
float servertime ;
CL_CalcClientTime ( ) ;
2010-03-14 14:35:56 +00:00
if ( cls . protocol = = CP_QUAKEWORLD & & ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV ) )
{
2009-11-04 21:16:50 +00:00
servertime = cl . servertime ;
2010-03-14 14:35:56 +00:00
nolerp = false ;
}
2009-11-04 21:16:50 +00:00
else
2010-03-14 14:35:56 +00:00
{
if ( ( cls . fteprotocolextensions & PEXT_ACCURATETIMINGS ) | | cls . protocol ! = CP_QUAKEWORLD )
servertime = cl . servertime ;
else
servertime = realtime ;
2005-11-26 03:02:55 +00:00
2010-03-14 14:35:56 +00:00
nolerp = ! CL_MayLerp ( ) & & cls . demoplayback ! = DPB_MVD & & cls . demoplayback ! = DPB_EZTV ;
# ifdef NQPROT
nolerp = nolerp & & cls . demoplayback ! = DPB_NETQUAKE ;
# endif
}
2008-01-16 06:36:24 +00:00
pack = CL_ProcessPacketEntities ( & servertime , nolerp ) ;
2005-11-26 03:02:55 +00:00
if ( ! pack )
return ;
2010-03-14 14:35:56 +00:00
/*
2009-11-04 21:16:50 +00:00
if ( ( cls . fteprotocolextensions & PEXT_ACCURATETIMINGS ) | | cls . protocol ! = CP_QUAKEWORLD )
servertime = cl . servertime ;
else
servertime = realtime ;
2010-03-14 14:35:56 +00:00
*/
2005-11-26 03:02:55 +00:00
autorotate = anglemod ( 100 * servertime ) ;
2009-04-02 22:25:54 +00:00
# ifdef CSQC_DAT
2009-04-06 00:34:32 +00:00
CSQC_DeltaStart ( servertime ) ;
2009-04-02 22:25:54 +00:00
# endif
2009-04-01 22:03:56 +00:00
2005-11-26 03:02:55 +00:00
for ( newpnum = 0 ; newpnum < pack - > num_entities ; newpnum + + )
{
state = & pack - > entities [ newpnum ] ;
if ( cl_numvisedicts = = MAX_VISEDICTS )
{
Con_Printf ( " Too many visible entities \n " ) ;
break ;
}
2009-04-01 22:03:56 +00:00
2009-04-02 22:25:54 +00:00
# ifdef CSQC_DAT
2009-04-06 00:34:32 +00:00
if ( CSQC_DeltaUpdate ( state ) )
2009-04-01 22:03:56 +00:00
continue ;
2009-04-02 22:25:54 +00:00
# endif
2009-04-01 22:03:56 +00:00
2005-11-26 03:02:55 +00:00
ent = & cl_visedicts [ cl_numvisedicts ] ;
ent - > forcedshader = NULL ;
le = & cl . lerpents [ state - > number ] ;
2008-12-23 02:55:20 +00:00
memset ( & ent - > framestate , 0 , sizeof ( ent - > framestate ) ) ;
2009-03-03 01:52:30 +00:00
VectorCopy ( le - > origin , ent - > origin ) ;
2005-11-26 03:02:55 +00:00
2009-11-04 21:16:50 +00:00
//bots or powerup glows. items always glow, bots can be disabled
if ( state - > modelindex ! = cl_playerindex | | r_powerupglow . ival )
if ( state - > effects & ( EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT ) | | state - > light [ 3 ] )
2005-11-26 03:02:55 +00:00
{
2009-11-04 21:16:50 +00:00
vec3_t colour ;
float radius ;
colour [ 0 ] = 0 ;
colour [ 1 ] = 0 ;
colour [ 2 ] = 0 ;
radius = 0 ;
if ( state - > effects & EF_BRIGHTLIGHT )
{
radius = max ( radius , 400 ) ;
colour [ 0 ] + = 0.2 ;
colour [ 1 ] + = 0.1 ;
colour [ 2 ] + = 0.05 ;
}
if ( state - > effects & EF_DIMLIGHT )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.2 ;
colour [ 1 ] + = 0.1 ;
colour [ 2 ] + = 0.05 ;
}
if ( state - > effects & EF_BLUE )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.05 ;
colour [ 1 ] + = 0.05 ;
colour [ 2 ] + = 0.3 ;
}
if ( state - > effects & EF_RED )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.5 ;
colour [ 1 ] + = 0.05 ;
colour [ 2 ] + = 0.05 ;
}
if ( state - > light [ 3 ] )
{
radius = max ( radius , state - > light [ 3 ] ) ;
colour [ 0 ] + = state - > light [ 0 ] / 1024.0f ;
colour [ 1 ] + = state - > light [ 1 ] / 1024.0f ;
colour [ 2 ] + = state - > light [ 2 ] / 1024.0f ;
}
if ( radius )
{
radius + = r_lightflicker . value ? ( rand ( ) & 31 ) : 0 ;
CL_NewDlightRGB ( state - > number , state - > origin , radius , 0.1 , colour [ 0 ] , colour [ 1 ] , colour [ 2 ] ) ;
}
2005-11-26 03:02:55 +00:00
}
// if set to invisible, skip
if ( state - > modelindex < 1 )
continue ;
// create a new entity
if ( cl_numvisedicts = = MAX_VISEDICTS )
break ; // object list is full
if ( CL_FilterModelindex ( state - > modelindex , state - > frame ) )
continue ;
model = cl . model_precache [ state - > modelindex ] ;
if ( ! model )
{
Con_DPrintf ( " Bad modelindex (%i) \n " , state - > modelindex ) ;
continue ;
}
cl_numvisedicts + + ;
ent - > forcedshader = NULL ;
ent - > visframe = 0 ;
ent - > keynum = state - > number ;
if ( cl_r2g . value & & state - > modelindex = = cl_rocketindex & & cl_rocketindex & & cl_grenadeindex )
ent - > model = cl . model_precache [ cl_grenadeindex ] ;
else
ent - > model = model ;
ent - > flags = state - > flags ;
2009-11-04 21:16:50 +00:00
if ( state - > effects & NQEF_ADDITIVE )
ent - > flags | = Q2RF_ADDITIVE ;
2005-11-26 03:02:55 +00:00
if ( state - > effects & EF_NODEPTHTEST )
ent - > flags | = RF_NODEPTHTEST ;
// set colormap
if ( state - > colormap & & ( state - > colormap < = MAX_CLIENTS )
& & ( gl_nocolors . value = = - 1 | | ( ent - > model /* && state->modelindex == cl_playerindex*/ ) ) )
{
2005-12-22 20:35:04 +00:00
// TODO: DP colormap/colormod extension?
2005-11-26 03:02:55 +00:00
ent - > scoreboard = & cl . players [ state - > colormap - 1 ] ;
}
else
{
ent - > scoreboard = NULL ;
}
// set skin
ent - > skinnum = state - > skinnum ;
ent - > abslight = state - > abslight ;
ent - > drawflags = state - > hexen2flags ;
2009-07-18 20:46:42 +00:00
CL_LerpNetFrameState ( FS_REG , & ent - > framestate , le ) ;
/*
2005-11-26 03:02:55 +00:00
// set frame
2009-07-18 20:46:42 +00:00
if ( le - > framechange = = le - > oldframechange )
ent - > framestate . g [ FS_REG ] . lerpfrac = 0 ;
else
{
ent - > framestate . g [ FS_REG ] . lerpfrac = 1 - ( servertime - le - > framechange ) / ( le - > framechange - le - > oldframechange ) ;
if ( ent - > framestate . g [ FS_REG ] . lerpfrac > 1 )
ent - > framestate . g [ FS_REG ] . lerpfrac = 1 ;
else if ( ent - > framestate . g [ FS_REG ] . lerpfrac < 0 )
{
ent - > framestate . g [ FS_REG ] . lerpfrac = 0 ;
//le->oldframechange = le->framechange;
}
}
2008-12-23 02:55:20 +00:00
ent - > framestate . g [ FS_REG ] . frame [ 0 ] = state - > frame ;
ent - > framestate . g [ FS_REG ] . frame [ 1 ] = le - > frame ;
2005-11-26 03:02:55 +00:00
2008-12-23 02:55:20 +00:00
ent - > framestate . g [ FS_REG ] . frametime [ 0 ] = cl . servertime - le - > framechange ;
ent - > framestate . g [ FS_REG ] . frametime [ 1 ] = cl . servertime - le - > oldframechange ;
2009-07-18 20:46:42 +00:00
*/
2005-11-26 03:02:55 +00:00
// f = (sin(realtime)+1)/2;
# ifdef PEXT_SCALE
//set scale
ent - > scale = state - > scale / 16.0 ;
# endif
2006-02-27 00:42:25 +00:00
ent - > shaderRGBAf [ 0 ] = ( state - > colormod [ 0 ] * 8.0f ) / 255 ;
ent - > shaderRGBAf [ 1 ] = ( state - > colormod [ 1 ] * 8.0f ) / 255 ;
ent - > shaderRGBAf [ 2 ] = ( state - > colormod [ 2 ] * 8.0f ) / 255 ;
ent - > shaderRGBAf [ 3 ] = state - > trans / 255.0f ;
2005-11-26 03:02:55 +00:00
# ifdef PEXT_FATNESS
//set trans
2009-07-05 18:45:53 +00:00
ent - > fatness = state - > fatness / 16.0 ;
2005-11-26 03:02:55 +00:00
# endif
// rotate binary objects locally
if ( model & & model - > flags & EF_ROTATE )
{
angles [ 0 ] = 0 ;
angles [ 1 ] = autorotate ;
angles [ 2 ] = 0 ;
if ( cl_item_bobbing . value )
ent - > origin [ 2 ] + = 5 + sin ( cl . time * 3 ) * 5 ; //don't let it into the ground
}
else
{
for ( i = 0 ; i < 3 ; i + + )
{
angles [ i ] = le - > angles [ i ] ;
}
}
VectorCopy ( angles , ent - > angles ) ;
2006-03-23 19:22:12 +00:00
if ( model & & model - > type = = mod_alias )
angles [ 0 ] * = - 1 ; //carmack screwed up when he added alias models - they pitch the wrong way.
2005-11-26 03:02:55 +00:00
AngleVectors ( angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
2009-04-01 22:03:56 +00:00
if ( ent - > keynum < = MAX_CLIENTS )
{
if ( ! cl . nolocalplayer [ 0 ] )
ent - > keynum + = MAX_EDICTS ;
}
2005-11-26 03:02:55 +00:00
if ( state - > tagentity )
{ //ent is attached to a tag, rotate this ent accordingly.
CL_RotateAroundTag ( ent , state - > number , state - > tagentity , state - > tagindex ) ;
}
// add automatic particle trails
if ( ! model | | ( ! ( model - > flags & ~ EF_ROTATE ) & & model - > particletrail < 0 & & model - > particleeffect < 0 ) )
continue ;
if ( ! cls . allow_anyparticles & & ! ( model - > flags & ~ EF_ROTATE ) )
continue ;
// scan the old entity display list for a matching
for ( i = 0 ; i < cl_oldnumvisedicts ; i + + )
{
if ( cl_oldvisedicts [ i ] . keynum = = ent - > keynum )
{
VectorCopy ( cl_oldvisedicts [ i ] . origin , old_origin ) ;
break ;
}
}
if ( i = = cl_oldnumvisedicts )
{
2008-11-09 22:29:28 +00:00
pe - > DelinkTrailstate ( & ( cl . lerpents [ state - > number ] . trailstate ) ) ;
pe - > DelinkTrailstate ( & ( cl . lerpents [ state - > number ] . emitstate ) ) ;
2005-11-26 03:02:55 +00:00
continue ; // not in last message
}
for ( i = 0 ; i < 3 ; i + + )
2005-11-26 23:23:03 +00:00
{
2005-11-26 03:02:55 +00:00
if ( abs ( old_origin [ i ] - ent - > origin [ i ] ) > 128 )
{ // no trail if too far
VectorCopy ( ent - > origin , old_origin ) ;
break ;
}
2005-11-26 23:23:03 +00:00
}
2005-11-26 03:02:55 +00:00
2005-11-26 23:23:03 +00:00
if ( model - > particletrail > = 0 )
{
2008-11-09 22:29:28 +00:00
if ( pe - > ParticleTrail ( old_origin , ent - > origin , model - > particletrail , & ( le - > trailstate ) ) )
pe - > ParticleTrailIndex ( old_origin , ent - > origin , model - > traildefaultindex , 0 , & ( le - > trailstate ) ) ;
2005-11-26 23:23:03 +00:00
}
2005-11-26 03:02:55 +00:00
{
extern cvar_t gl_part_flame ;
2009-11-04 21:16:50 +00:00
if ( cls . allow_anyparticles & & gl_part_flame . ival )
2005-11-26 03:02:55 +00:00
{
P_EmitEffect ( ent - > origin , model - > particleeffect , & ( le - > emitstate ) ) ;
}
}
//dlights are not so customisable.
if ( r_rocketlight . value )
{
float rad = 0 ;
vec3_t dclr ;
dclr [ 0 ] = 0.20 ;
dclr [ 1 ] = 0.10 ;
dclr [ 2 ] = 0 ;
if ( model - > flags & EF_ROCKET )
{
2009-11-04 21:16:50 +00:00
# pragma message("Replace this flag on load for hexen2 models")
2005-11-26 03:02:55 +00:00
if ( strncmp ( model - > name , " models/sflesh " , 13 ) )
{ //hmm. hexen spider gibs...
rad = 200 ;
dclr [ 2 ] = 0.05 ;
}
}
2008-11-09 22:29:28 +00:00
else if ( model - > flags & EFH2_FIREBALL )
2005-11-26 03:02:55 +00:00
{
rad = 120 - ( rand ( ) % 20 ) ;
}
2008-11-09 22:29:28 +00:00
else if ( model - > flags & EFH2_ACIDBALL )
2005-11-26 03:02:55 +00:00
{
rad = 120 - ( rand ( ) % 20 ) ;
}
2008-11-09 22:29:28 +00:00
else if ( model - > flags & EFH2_SPIT )
2005-11-26 03:02:55 +00:00
{
// as far as I can tell this effect inverses the light...
dclr [ 0 ] = - dclr [ 0 ] ;
dclr [ 0 ] = - dclr [ 1 ] ;
dclr [ 0 ] = - dclr [ 2 ] ;
rad = 120 - ( rand ( ) % 20 ) ;
}
if ( rad )
{
dl = CL_AllocDlight ( state - > number ) ;
2009-07-05 18:45:53 +00:00
memcpy ( dl - > axis , ent - > axis , sizeof ( dl - > axis ) ) ;
2005-11-26 03:02:55 +00:00
VectorCopy ( ent - > origin , dl - > origin ) ;
dl - > die = ( float ) cl . time ;
if ( model - > flags & EF_ROCKET )
dl - > origin [ 2 ] + = 1 ; // is this even necessary
2006-04-21 05:23:51 +00:00
dl - > radius = rad * r_rocketlight . value ;
2005-11-26 03:02:55 +00:00
VectorCopy ( dclr , dl - > color ) ;
}
}
}
2009-04-02 22:25:54 +00:00
# ifdef CSQC_DAT
2009-04-06 00:34:32 +00:00
CSQC_DeltaEnd ( ) ;
2009-04-02 22:25:54 +00:00
# endif
2005-11-26 03:02:55 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PROJECTILE PARSING / LINKING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
typedef struct
{
int modelindex ;
vec3_t origin ;
vec3_t angles ;
} projectile_t ;
# define MAX_PROJECTILES 32
projectile_t cl_projectiles [ MAX_PROJECTILES ] ;
int cl_num_projectiles ;
extern int cl_spikeindex ;
void CL_ClearProjectiles ( void )
{
cl_num_projectiles = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_ParseProjectiles
Nails are passed as efficient temporary entities
= = = = = = = = = = = = = = = = = = = = =
*/
2004-12-08 04:14:52 +00:00
void CL_ParseProjectiles ( int modelindex , qboolean nails2 )
2004-08-23 00:15:46 +00:00
{
int i , c , j ;
qbyte bits [ 6 ] ;
projectile_t * pr ;
c = MSG_ReadByte ( ) ;
for ( i = 0 ; i < c ; i + + )
{
2004-12-08 04:14:52 +00:00
if ( nails2 )
MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
for ( j = 0 ; j < 6 ; j + + )
bits [ j ] = MSG_ReadByte ( ) ;
if ( cl_num_projectiles = = MAX_PROJECTILES )
continue ;
pr = & cl_projectiles [ cl_num_projectiles ] ;
cl_num_projectiles + + ;
pr - > modelindex = modelindex ;
pr - > origin [ 0 ] = ( ( bits [ 0 ] + ( ( bits [ 1 ] & 15 ) < < 8 ) ) < < 1 ) - 4096 ;
pr - > origin [ 1 ] = ( ( ( bits [ 1 ] > > 4 ) + ( bits [ 2 ] < < 4 ) ) < < 1 ) - 4096 ;
pr - > origin [ 2 ] = ( ( bits [ 3 ] + ( ( bits [ 4 ] & 15 ) < < 8 ) ) < < 1 ) - 4096 ;
2009-11-04 21:16:50 +00:00
pr - > angles [ 0 ] = 360 * ( ( ( int ) bits [ 4 ] > > 4 ) / 16.0f + 1 / 32.0f ) ;
2004-12-24 08:45:56 +00:00
pr - > angles [ 1 ] = 360 * ( int ) bits [ 5 ] / 256.0f ;
2004-08-23 00:15:46 +00:00
}
}
/*
= = = = = = = = = = = = =
CL_LinkProjectiles
= = = = = = = = = = = = =
*/
void CL_LinkProjectiles ( void )
{
int i ;
projectile_t * pr ;
entity_t * ent ;
for ( i = 0 , pr = cl_projectiles ; i < cl_num_projectiles ; i + + , pr + + )
{
// grab an entity to fill in
if ( cl_numvisedicts = = MAX_VISEDICTS )
break ; // object list is full
ent = & cl_visedicts [ cl_numvisedicts ] ;
cl_numvisedicts + + ;
ent - > keynum = 0 ;
if ( pr - > modelindex < 1 )
continue ;
2009-11-04 21:16:50 +00:00
2005-11-30 23:12:08 +00:00
ent - > forcedshader = NULL ;
2004-08-23 00:15:46 +00:00
ent - > model = cl . model_precache [ pr - > modelindex ] ;
ent - > skinnum = 0 ;
2008-12-23 02:55:20 +00:00
memset ( & ent - > framestate , 0 , sizeof ( ent - > framestate ) ) ;
2005-07-08 00:37:52 +00:00
ent - > flags = 0 ;
2004-08-23 00:15:46 +00:00
ent - > scoreboard = NULL ;
# ifdef PEXT_SCALE
ent - > scale = 1 ;
# endif
2006-02-27 00:42:25 +00:00
ent - > shaderRGBAf [ 0 ] = 1 ;
ent - > shaderRGBAf [ 1 ] = 1 ;
ent - > shaderRGBAf [ 2 ] = 1 ;
ent - > shaderRGBAf [ 3 ] = 1 ;
2004-08-23 00:15:46 +00:00
VectorCopy ( pr - > origin , ent - > origin ) ;
VectorCopy ( pr - > angles , ent - > angles ) ;
2004-12-24 08:45:56 +00:00
ent - > angles [ 0 ] * = - 1 ;
AngleVectors ( ent - > angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
ent - > angles [ 0 ] * = - 1 ;
2004-08-23 00:15:46 +00:00
}
}
//========================================
2005-01-17 17:40:37 +00:00
extern int cl_spikeindex , cl_playerindex , cl_flagindex , cl_rocketindex , cl_grenadeindex ;
2004-08-23 00:15:46 +00:00
entity_t * CL_NewTempEntity ( void ) ;
# define DF_ORIGIN 1
# define DF_ANGLES (1<<3)
# define DF_EFFECTS (1<<6)
# define DF_SKINNUM (1<<7)
# define DF_DEAD (1<<8)
# define DF_GIB (1<<9)
# define DF_WEAPONFRAME (1<<10)
# define DF_MODEL (1<<11)
static int MVD_TranslateFlags ( int src )
{
int dst = 0 ;
if ( src & DF_EFFECTS )
dst | = PF_EFFECTS ;
if ( src & DF_SKINNUM )
dst | = PF_SKINNUM ;
if ( src & DF_DEAD )
dst | = PF_DEAD ;
if ( src & DF_GIB )
dst | = PF_GIB ;
if ( src & DF_WEAPONFRAME )
dst | = PF_WEAPONFRAME ;
if ( src & DF_MODEL )
dst | = PF_MODEL ;
return dst ;
}
/*
= = = = = = = = = = = = = = = = = = =
CL_ParsePlayerinfo
= = = = = = = = = = = = = = = = = = =
*/
2005-04-26 16:04:12 +00:00
extern int parsecountmod , oldparsecountmod ;
2004-08-23 00:15:46 +00:00
extern double parsecounttime ;
int lastplayerinfo ;
void CL_ParsePlayerinfo ( void )
{
int msec ;
unsigned int flags ;
player_info_t * info ;
2005-04-26 16:04:12 +00:00
player_state_t * state , * oldstate ;
2004-08-23 00:15:46 +00:00
int num ;
int i ;
2006-06-02 17:42:36 +00:00
int newf ;
2004-09-13 02:19:15 +00:00
vec3_t org ;
2004-08-23 00:15:46 +00:00
lastplayerinfo = num = MSG_ReadByte ( ) ;
if ( num > = MAX_CLIENTS )
Host_EndGame ( " CL_ParsePlayerinfo: bad num " ) ;
info = & cl . players [ num ] ;
2005-04-26 16:04:12 +00:00
oldstate = & cl . frames [ oldparsecountmod ] . playerstate [ num ] ;
2004-08-23 00:15:46 +00:00
state = & cl . frames [ parsecountmod ] . playerstate [ num ] ;
2008-01-09 00:52:31 +00:00
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
2004-08-23 00:15:46 +00:00
{
player_state_t * prevstate , dummy ;
if ( ! cl . parsecount | | info - > prevcount > cl . parsecount | | cl . parsecount - info - > prevcount > = UPDATE_BACKUP - 1 )
{
memset ( & dummy , 0 , sizeof ( dummy ) ) ;
prevstate = & dummy ;
}
else
{
prevstate = & cl . frames [ info - > prevcount & UPDATE_MASK ] . playerstate [ num ] ;
}
memcpy ( state , prevstate , sizeof ( player_state_t ) ) ;
2004-08-27 00:37:05 +00:00
info - > prevcount = cl . parsecount ;
2004-08-23 00:15:46 +00:00
2005-11-30 01:20:53 +00:00
if ( cls . findtrack & & info - > stats [ STAT_HEALTH ] > 0 )
2004-08-23 00:15:46 +00:00
{
2005-11-30 01:20:53 +00:00
// extern int ideal_track;
autocam [ 0 ] = CAM_TRACK ;
Cam_Lock ( 0 , num ) ;
// ideal_track = num;
2004-08-23 00:15:46 +00:00
cls . findtrack = false ;
}
2005-11-30 01:20:53 +00:00
2004-08-23 00:15:46 +00:00
flags = MSG_ReadShort ( ) ;
state - > flags = MVD_TranslateFlags ( flags ) ;
state - > messagenum = cl . parsecount ;
state - > command . msec = 0 ;
state - > frame = MSG_ReadByte ( ) ;
state - > state_time = parsecounttime ;
state - > command . msec = 0 ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( flags & ( DF_ORIGIN < < i ) )
state - > origin [ i ] = MSG_ReadCoord ( ) ;
}
for ( i = 0 ; i < 3 ; i + + )
{
if ( flags & ( DF_ANGLES < < i ) )
2004-08-27 00:37:05 +00:00
{
state - > command . angles [ i ] = MSG_ReadShort ( ) ;
}
state - > viewangles [ i ] = state - > command . angles [ i ] * ( 360.0 / 65536 ) ;
2004-08-23 00:15:46 +00:00
}
if ( flags & DF_MODEL )
state - > modelindex = MSG_ReadByte ( ) ;
if ( flags & DF_SKINNUM )
state - > skinnum = MSG_ReadByte ( ) ;
if ( flags & DF_EFFECTS )
state - > effects = MSG_ReadByte ( ) ;
if ( flags & DF_WEAPONFRAME )
state - > weaponframe = MSG_ReadByte ( ) ;
state - > hullnum = 1 ;
2005-07-01 19:23:00 +00:00
state - > scale = 1 * 16 ;
2006-02-27 00:42:25 +00:00
state - > alpha = 255 ;
2004-08-23 00:15:46 +00:00
state - > fatness = 0 ;
2006-03-06 18:53:09 +00:00
state - > colourmod [ 0 ] = 32 ;
state - > colourmod [ 1 ] = 32 ;
state - > colourmod [ 2 ] = 32 ;
2004-08-27 00:37:05 +00:00
state - > pm_type = PM_NORMAL ;
2005-04-26 16:04:12 +00:00
TP_ParsePlayerInfo ( oldstate , state , info ) ;
2005-06-07 04:40:16 +00:00
if ( cl . splitclients < MAX_SPLITS )
{
extern cvar_t cl_splitscreen ;
if ( cl . splitclients < cl_splitscreen . value + 1 )
{
for ( i = 0 ; i < cl . splitclients ; i + + )
if ( autocam [ i ] & & spec_track [ i ] = = num )
return ;
if ( i = = cl . splitclients )
{
autocam [ cl . splitclients ] = CAM_TRACK ;
spec_track [ cl . splitclients ] = num ;
cl . splitclients + + ;
}
}
}
2004-08-23 00:15:46 +00:00
return ;
}
2009-05-30 23:48:18 +00:00
flags = ( unsigned short ) MSG_ReadShort ( ) ;
2004-08-23 00:15:46 +00:00
2009-05-30 23:48:18 +00:00
if ( cls . fteprotocolextensions & ( PEXT_HULLSIZE | PEXT_TRANS | PEXT_SCALE | PEXT_FATNESS ) )
2004-08-23 00:15:46 +00:00
if ( flags & PF_EXTRA_PFS )
flags | = MSG_ReadByte ( ) < < 16 ;
2009-05-30 23:48:18 +00:00
state - > flags = flags ;
2004-08-23 00:15:46 +00:00
state - > messagenum = cl . parsecount ;
2004-09-07 18:22:30 +00:00
org [ 0 ] = MSG_ReadCoord ( ) ;
org [ 1 ] = MSG_ReadCoord ( ) ;
org [ 2 ] = MSG_ReadCoord ( ) ;
VectorCopy ( org , state - > origin ) ;
2004-08-23 00:15:46 +00:00
2006-06-02 17:42:36 +00:00
newf = MSG_ReadByte ( ) ;
if ( state - > frame ! = newf )
2004-08-23 00:15:46 +00:00
{
// state->lerpstarttime = realtime;
2006-06-02 17:42:36 +00:00
state - > frame = newf ;
2004-08-23 00:15:46 +00:00
}
// the other player's last move was likely some time
// before the packet was sent out, so accurately track
// the exact time it was valid at
if ( flags & PF_MSEC )
{
msec = MSG_ReadByte ( ) ;
state - > state_time = parsecounttime - msec * 0.001 ;
}
else
state - > state_time = parsecounttime ;
if ( flags & PF_COMMAND )
{
MSG_ReadDeltaUsercmd ( & nullcmd , & state - > command ) ;
state - > viewangles [ 0 ] = state - > command . angles [ 0 ] * ( 360.0 / 65536 ) ;
state - > viewangles [ 1 ] = state - > command . angles [ 1 ] * ( 360.0 / 65536 ) ;
state - > viewangles [ 2 ] = state - > command . angles [ 2 ] * ( 360.0 / 65536 ) ;
2009-07-06 01:20:20 +00:00
if ( ! ( cls . z_ext & Z_EXT_VWEP ) )
state - > command . impulse = 0 ;
2004-08-23 00:15:46 +00:00
}
for ( i = 0 ; i < 3 ; i + + )
{
if ( flags & ( PF_VELOCITY1 < < i ) )
state - > velocity [ i ] = MSG_ReadShort ( ) ;
else
state - > velocity [ i ] = 0 ;
}
if ( flags & PF_MODEL )
state - > modelindex = MSG_ReadByte ( ) ;
else
state - > modelindex = cl_playerindex ;
if ( flags & PF_SKINNUM )
{
state - > skinnum = MSG_ReadByte ( ) ;
if ( state - > skinnum & ( 1 < < 7 ) & & ( flags & PF_MODEL ) )
{
state - > modelindex + = 256 ;
state - > skinnum - = ( 1 < < 7 ) ;
}
}
else
state - > skinnum = 0 ;
if ( flags & PF_EFFECTS )
state - > effects = MSG_ReadByte ( ) ;
else
state - > effects = 0 ;
if ( flags & PF_WEAPONFRAME )
state - > weaponframe = MSG_ReadByte ( ) ;
else
state - > weaponframe = 0 ;
2008-11-09 22:29:28 +00:00
if ( cl . worldmodel & & cl . worldmodel - > fromgame = = fg_quake )
2005-04-16 16:21:27 +00:00
state - > hullnum = 1 ;
else
state - > hullnum = 56 ;
2005-07-01 19:23:00 +00:00
state - > scale = 1 * 16 ;
2006-02-27 00:42:25 +00:00
state - > alpha = 255 ;
2004-08-23 00:15:46 +00:00
state - > fatness = 0 ;
# ifdef PEXT_SCALE
2005-07-01 19:23:00 +00:00
if ( flags & PF_SCALE_Z & & cls . fteprotocolextensions & PEXT_SCALE )
state - > scale = ( float ) MSG_ReadByte ( ) / 100 ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_TRANS
2005-07-01 19:23:00 +00:00
if ( flags & PF_TRANS_Z & & cls . fteprotocolextensions & PEXT_TRANS )
2006-02-27 00:42:25 +00:00
state - > alpha = MSG_ReadByte ( ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_FATNESS
2005-07-01 19:23:00 +00:00
if ( flags & PF_FATNESS_Z & & cls . fteprotocolextensions & PEXT_FATNESS )
2009-07-05 18:45:53 +00:00
state - > fatness = ( float ) MSG_ReadChar ( ) / 16 ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_HULLSIZE
2005-07-01 19:23:00 +00:00
if ( cls . fteprotocolextensions & PEXT_HULLSIZE )
{
if ( flags & PF_HULLSIZE_Z )
state - > hullnum = MSG_ReadByte ( ) ;
}
2004-08-23 00:15:46 +00:00
//should be passed to player move func.
# endif
2006-02-27 00:42:25 +00:00
if ( cls . fteprotocolextensions & PEXT_COLOURMOD & & flags & PF_COLOURMOD )
{
state - > colourmod [ 0 ] = MSG_ReadByte ( ) ;
state - > colourmod [ 1 ] = MSG_ReadByte ( ) ;
state - > colourmod [ 2 ] = MSG_ReadByte ( ) ;
}
else
{
state - > colourmod [ 0 ] = 32 ;
state - > colourmod [ 1 ] = 32 ;
state - > colourmod [ 2 ] = 32 ;
}
2005-07-01 19:23:00 +00:00
if ( cls . z_ext & Z_EXT_PM_TYPE )
{
int pm_code ;
2004-08-23 00:15:46 +00:00
pm_code = ( flags & PF_PMC_MASK ) > > PF_PMC_SHIFT ;
if ( pm_code = = PMC_NORMAL | | pm_code = = PMC_NORMAL_JUMP_HELD )
{
if ( flags & PF_DEAD )
state - > pm_type = PM_DEAD ;
else
{
state - > pm_type = PM_NORMAL ;
state - > jump_held = ( pm_code = = PMC_NORMAL_JUMP_HELD ) ;
}
}
else if ( pm_code = = PMC_OLD_SPECTATOR )
state - > pm_type = PM_OLD_SPECTATOR ;
else
{
if ( cls . z_ext & Z_EXT_PM_TYPE_NEW )
{
if ( pm_code = = PMC_SPECTATOR )
state - > pm_type = PM_SPECTATOR ;
else if ( pm_code = = PMC_FLY )
state - > pm_type = PM_FLY ;
else if ( pm_code = = PMC_NONE )
state - > pm_type = PM_NONE ;
else if ( pm_code = = PMC_FREEZE )
state - > pm_type = PM_FREEZE ;
else {
// future extension?
goto guess_pm_type ;
}
}
else
{
// future extension?
goto guess_pm_type ;
}
}
}
else
{
guess_pm_type :
if ( cl . players [ num ] . spectator )
state - > pm_type = PM_OLD_SPECTATOR ;
else if ( flags & PF_DEAD )
state - > pm_type = PM_DEAD ;
else
state - > pm_type = PM_NORMAL ;
}
2009-07-18 20:46:42 +00:00
/* if (cl.lerpplayers[num].frame != state->frame)
2005-08-26 22:56:51 +00:00
{
cl . lerpplayers [ num ] . oldframechange = cl . lerpplayers [ num ] . framechange ;
2006-07-24 04:24:41 +00:00
cl . lerpplayers [ num ] . framechange = cl . time ;
2005-08-26 22:56:51 +00:00
cl . lerpplayers [ num ] . frame = state - > frame ;
//don't care about position interpolation.
}
2009-07-18 20:46:42 +00:00
*/
2005-07-16 00:53:08 +00:00
TP_ParsePlayerInfo ( oldstate , state , info ) ;
2004-08-23 00:15:46 +00:00
}
void CL_ParseClientPersist ( void )
{
player_info_t * info ;
int flags ;
flags = MSG_ReadShort ( ) ;
info = & cl . players [ lastplayerinfo ] ;
if ( flags & 1 )
info - > vweapindex = MSG_ReadShort ( ) ;
}
/*
= = = = = = = = = = = = = = = =
CL_AddFlagModels
Called when the CTF flags are set
= = = = = = = = = = = = = = = =
*/
void CL_AddFlagModels ( entity_t * ent , int team )
{
int i ;
float f ;
vec3_t v_forward , v_right , v_up ;
entity_t * newent ;
2004-11-17 17:55:19 +00:00
vec3_t angles ;
2009-02-03 00:08:32 +00:00
float offs = 0 ;
2004-08-23 00:15:46 +00:00
if ( cl_flagindex = = - 1 )
return ;
2008-12-23 02:55:20 +00:00
for ( i = 0 ; i < 2 ; i + + )
{
f = 14 ;
if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 29 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 40 ) {
if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 29 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 34 ) { //axpain
if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 29 ) f = f + 2 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 30 ) f = f + 8 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 31 ) f = f + 12 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 32 ) f = f + 11 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 33 ) f = f + 10 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 34 ) f = f + 4 ;
} else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 35 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 40 ) { // pain
if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 35 ) f = f + 2 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 36 ) f = f + 10 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 37 ) f = f + 10 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 38 ) f = f + 8 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 39 ) f = f + 4 ;
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] = = 40 ) f = f + 2 ;
}
} else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 103 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 118 ) {
if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 103 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 104 ) f = f + 6 ; //nailattack
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 105 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 106 ) f = f + 6 ; //light
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 107 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 112 ) f = f + 7 ; //rocketattack
else if ( ent - > framestate . g [ FS_REG ] . frame [ i ] > = 112 & & ent - > framestate . g [ FS_REG ] . frame [ i ] < = 118 ) f = f + 7 ; //shotattack
}
offs + = f + ( ( i = = 0 ) ? ( ent - > framestate . g [ FS_REG ] . lerpfrac ) : ( 1 - ent - > framestate . g [ FS_REG ] . lerpfrac ) ) ;
2004-08-23 00:15:46 +00:00
}
newent = CL_NewTempEntity ( ) ;
newent - > model = cl . model_precache [ cl_flagindex ] ;
newent - > skinnum = team ;
AngleVectors ( ent - > angles , v_forward , v_right , v_up ) ;
v_forward [ 2 ] = - v_forward [ 2 ] ; // reverse z component
for ( i = 0 ; i < 3 ; i + + )
2008-12-23 02:55:20 +00:00
newent - > origin [ i ] = ent - > origin [ i ] - offs * v_forward [ i ] + 22 * v_right [ i ] ;
2004-08-23 00:15:46 +00:00
newent - > origin [ 2 ] - = 16 ;
2009-03-03 01:52:30 +00:00
VectorCopy ( ent - > angles , newent - > angles ) ;
2004-08-23 00:15:46 +00:00
newent - > angles [ 2 ] - = 45 ;
2004-11-17 17:55:19 +00:00
VectorCopy ( newent - > angles , angles ) ;
angles [ 0 ] * = - 1 ;
AngleVectors ( angles , newent - > axis [ 0 ] , newent - > axis [ 1 ] , newent - > axis [ 2 ] ) ;
VectorInverse ( newent - > axis [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
2009-07-06 01:20:20 +00:00
void CL_AddVWeapModel ( entity_t * player , model_t * model )
2004-08-23 00:15:46 +00:00
{
entity_t * newent ;
2004-11-17 17:55:19 +00:00
vec3_t angles ;
2004-08-23 00:15:46 +00:00
newent = CL_NewTempEntity ( ) ;
2009-07-19 15:08:30 +00:00
newent - > keynum = player - > keynum ;
2004-08-23 00:15:46 +00:00
VectorCopy ( player - > origin , newent - > origin ) ;
VectorCopy ( player - > angles , newent - > angles ) ;
newent - > skinnum = player - > skinnum ;
2009-07-06 01:20:20 +00:00
newent - > model = model ;
2008-12-23 02:55:20 +00:00
newent - > framestate = player - > framestate ;
2004-11-17 17:55:19 +00:00
VectorCopy ( newent - > angles , angles ) ;
angles [ 0 ] * = - 1 ;
AngleVectors ( angles , newent - > axis [ 0 ] , newent - > axis [ 1 ] , newent - > axis [ 2 ] ) ;
VectorInverse ( newent - > axis [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = =
CL_LinkPlayers
Create visible entities in the correct position
for all current players
= = = = = = = = = = = = =
*/
2009-07-17 22:28:16 +00:00
vec3_t nametagorg [ MAX_CLIENTS ] ;
qboolean nametagseen [ MAX_CLIENTS ] ;
2004-08-23 00:15:46 +00:00
void CL_LinkPlayers ( void )
{
int pnum ;
int j ;
player_info_t * info ;
player_state_t * state ;
player_state_t exact ;
double playertime ;
entity_t * ent ;
int msec ;
frame_t * frame ;
2005-10-01 03:09:17 +00:00
frame_t * fromf ;
2004-08-23 00:15:46 +00:00
int oldphysent ;
2004-11-17 17:55:19 +00:00
vec3_t angles ;
2008-01-24 01:24:10 +00:00
float * org ;
2010-03-14 14:35:56 +00:00
qboolean predictplayers ;
2004-08-23 00:15:46 +00:00
2009-04-01 22:03:56 +00:00
if ( ! cl . worldmodel | | cl . worldmodel - > needload )
return ;
2004-08-23 00:15:46 +00:00
playertime = realtime - cls . latency + 0.02 ;
if ( playertime > realtime )
playertime = realtime ;
2005-10-01 03:09:17 +00:00
frame = & cl . frames [ cl . validsequence & UPDATE_MASK ] ;
fromf = & cl . frames [ cl . oldvalidsequence & UPDATE_MASK ] ;
2004-08-23 00:15:46 +00:00
2010-03-14 14:35:56 +00:00
predictplayers = cl_predict_players . ival | | cl_predict_players2 . ival ;
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
predictplayers = false ;
2005-02-06 02:47:36 +00:00
for ( j = 0 , info = cl . players , state = frame - > playerstate ; j < MAX_CLIENTS
2004-08-23 00:15:46 +00:00
; j + + , info + + , state + + )
{
2009-07-17 22:28:16 +00:00
nametagseen [ j ] = false ;
2005-10-01 03:09:17 +00:00
if ( state - > messagenum ! = cl . validsequence )
2009-04-01 22:03:56 +00:00
{
2009-04-02 22:25:54 +00:00
# ifdef CSQC_DAT
2009-04-06 00:34:32 +00:00
CSQC_DeltaPlayer ( j , NULL ) ;
2009-04-02 22:25:54 +00:00
# endif
2004-08-23 00:15:46 +00:00
continue ; // not present this frame
2009-04-01 22:03:56 +00:00
}
2009-04-02 22:25:54 +00:00
# ifdef CSQC_DAT
2009-04-06 00:34:32 +00:00
if ( CSQC_DeltaPlayer ( j , state ) )
2009-04-01 22:03:56 +00:00
continue ;
2009-04-02 22:25:54 +00:00
# endif
2004-08-23 00:15:46 +00:00
2009-11-04 21:16:50 +00:00
if ( info - > spectator )
continue ;
2004-08-23 00:15:46 +00:00
// spawn light flashes, even ones coming from invisible objects
2009-07-05 18:45:53 +00:00
if ( r_powerupglow . value & & ! ( r_powerupglow . value = = 2 & & j = = cl . playernum [ 0 ] )
& & ( state - > effects & ( EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT ) ) )
2004-08-23 00:15:46 +00:00
{
2009-07-05 18:45:53 +00:00
vec3_t colour ;
float radius ;
2008-01-24 01:24:10 +00:00
org = ( j = = cl . playernum [ 0 ] ) ? cl . simorg [ 0 ] : state - > origin ;
2009-07-05 18:45:53 +00:00
colour [ 0 ] = 0 ;
colour [ 1 ] = 0 ;
colour [ 2 ] = 0 ;
radius = 0 ;
2008-01-24 01:24:10 +00:00
2009-07-05 18:45:53 +00:00
if ( state - > effects & EF_BRIGHTLIGHT )
{
radius = max ( radius , 400 ) ;
colour [ 0 ] + = 0.2 ;
colour [ 1 ] + = 0.1 ;
colour [ 2 ] + = 0.05 ;
}
if ( state - > effects & EF_DIMLIGHT )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.2 ;
colour [ 1 ] + = 0.1 ;
colour [ 2 ] + = 0.05 ;
}
if ( state - > effects & EF_BLUE )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.05 ;
colour [ 1 ] + = 0.05 ;
colour [ 2 ] + = 0.3 ;
}
if ( state - > effects & EF_RED )
{
radius = max ( radius , 200 ) ;
colour [ 0 ] + = 0.5 ;
colour [ 1 ] + = 0.05 ;
colour [ 2 ] + = 0.05 ;
}
if ( radius )
{
radius + = r_lightflicker . value ? ( rand ( ) & 31 ) : 0 ;
2009-11-04 21:16:50 +00:00
CL_NewDlightRGB ( j + 1 , org , radius , 0.1 , colour [ 0 ] , colour [ 1 ] , colour [ 2 ] ) - > flags & = ~ LFLAG_ALLOW_FLASH ;
2009-07-05 18:45:53 +00:00
}
2004-08-23 00:15:46 +00:00
}
2004-12-08 04:14:52 +00:00
if ( state - > modelindex < 1 )
2004-08-23 00:15:46 +00:00
continue ;
2005-01-18 20:15:20 +00:00
if ( CL_FilterModelindex ( state - > modelindex , state - > frame ) )
continue ;
2004-08-23 00:15:46 +00:00
/*
if ( ! Cam_DrawPlayer ( j ) )
continue ;
*/
// grab an entity to fill in
if ( cl_numvisedicts = = MAX_VISEDICTS )
break ; // object list is full
ent = & cl_visedicts [ cl_numvisedicts ] ;
cl_numvisedicts + + ;
ent - > keynum = j + 1 ;
ent - > flags = 0 ;
2005-10-01 15:44:36 +00:00
ent - > forcedshader = NULL ;
2009-07-25 11:05:06 +00:00
//the extra modelindex check is to stop lame mods from using vweps with rings
if ( state - > command . impulse & & cl . model_precache_vwep [ 0 ] & & state - > modelindex = = cl_playerindex )
2009-07-06 01:20:20 +00:00
ent - > model = cl . model_precache_vwep [ 0 ] ;
else
ent - > model = cl . model_precache [ state - > modelindex ] ;
2005-02-06 02:47:36 +00:00
ent - > skinnum = state - > skinnum ;
2004-08-23 00:15:46 +00:00
2009-07-18 20:46:42 +00:00
CL_UpdateNetFrameLerpState ( false , state - > frame , & cl . lerpplayers [ j ] ) ;
CL_LerpNetFrameState ( FS_REG , & ent - > framestate , & cl . lerpplayers [ j ] ) ;
2004-08-23 00:15:46 +00:00
if ( state - > modelindex = = cl_playerindex )
ent - > scoreboard = info ; // use custom skin
else
ent - > scoreboard = NULL ;
# ifdef PEXT_SCALE
2005-07-01 19:23:00 +00:00
ent - > scale = state - > scale / 16.0f ;
2004-08-23 00:15:46 +00:00
# endif
2006-02-27 00:42:25 +00:00
ent - > shaderRGBAf [ 0 ] = state - > colourmod [ 0 ] / 32 ;
ent - > shaderRGBAf [ 1 ] = state - > colourmod [ 1 ] / 32 ;
ent - > shaderRGBAf [ 2 ] = state - > colourmod [ 2 ] / 32 ;
ent - > shaderRGBAf [ 3 ] = state - > alpha / 255 ;
2009-07-05 18:45:53 +00:00
ent - > fatness = state - > fatness / 16 ;
2004-08-23 00:15:46 +00:00
//
// angles
//
2004-11-17 17:55:19 +00:00
angles [ PITCH ] = - state - > viewangles [ PITCH ] / 3 ;
angles [ YAW ] = state - > viewangles [ YAW ] ;
angles [ ROLL ] = 0 ;
angles [ ROLL ] = V_CalcRoll ( angles , state - > velocity ) * 4 ;
2004-08-23 00:15:46 +00:00
// the player object gets added with flags | 2
for ( pnum = 0 ; pnum < cl . splitclients ; pnum + + )
{
if ( j = = cl . playernum [ pnum ] )
{
2005-06-14 04:52:10 +00:00
/* if (cl.spectator)
2004-08-23 00:15:46 +00:00
{
cl_numvisedicts - - ;
continue ;
}
2005-06-14 04:52:10 +00:00
*/ angles [ 0 ] = - 1 * cl . viewangles [ pnum ] [ 0 ] / 3 ;
2004-11-17 17:55:19 +00:00
angles [ 1 ] = cl . viewangles [ pnum ] [ 1 ] ;
angles [ 2 ] = cl . viewangles [ pnum ] [ 2 ] ;
2004-08-23 00:15:46 +00:00
ent - > origin [ 0 ] = cl . simorg [ pnum ] [ 0 ] ;
ent - > origin [ 1 ] = cl . simorg [ pnum ] [ 1 ] ;
ent - > origin [ 2 ] = cl . simorg [ pnum ] [ 2 ] + cl . crouch [ pnum ] ;
2006-11-03 15:53:04 +00:00
ent - > flags | = Q2RF_EXTERNALMODEL ;
2004-08-23 00:15:46 +00:00
break ;
}
}
2004-11-17 17:55:19 +00:00
VectorCopy ( angles , ent - > angles ) ;
angles [ 0 ] * = - 1 ;
AngleVectors ( angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
VectorInverse ( ent - > axis [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
// only predict half the move to minimize overruns
msec = 500 * ( playertime - state - > state_time ) ;
2006-01-28 02:35:40 +00:00
/*
2005-10-01 03:09:17 +00:00
if ( 1 )
2004-08-23 00:15:46 +00:00
{
2005-10-01 03:09:17 +00:00
float f ;
int i ;
f = ( cl . gametime - cl . servertime ) / ( cl . gametime - cl . oldgametime ) ;
if ( f < 0 )
f = 0 ;
if ( f > 1 )
f = 1 ;
for ( i = 0 ; i < 3 ; i + + )
{
ent - > origin [ i ] = state - > origin [ i ] +
f * ( fromf - > playerstate [ j ] . origin [ i ] - state - > origin [ i ] ) ;
}
}
2006-01-28 02:35:40 +00:00
else
*/
if ( pnum < cl . splitclients )
2005-10-01 03:09:17 +00:00
{ //this is a local player
2004-08-23 00:15:46 +00:00
}
2010-03-14 14:35:56 +00:00
else if ( msec < = 0 | | ( ! predictplayers ) )
2004-08-23 00:15:46 +00:00
{
VectorCopy ( state - > origin , ent - > origin ) ;
//Con_DPrintf ("nopredict\n");
}
else
{
// predict players movement
if ( msec > 255 )
msec = 255 ;
state - > command . msec = msec ;
//Con_DPrintf ("predict: %i\n", msec);
oldphysent = pmove . numphysent ;
CL_SetSolidPlayers ( j ) ;
CL_PredictUsercmd ( 0 , state , & exact , & state - > command ) ; //uses player 0's maxspeed/grav...
pmove . numphysent = oldphysent ;
VectorCopy ( exact . origin , ent - > origin ) ;
}
2009-07-17 22:28:16 +00:00
VectorCopy ( ent - > origin , nametagorg [ j ] ) ;
nametagseen [ j ] = true ;
2005-04-16 16:21:27 +00:00
if ( state - > effects & QWEF_FLAG1 )
2004-08-23 00:15:46 +00:00
CL_AddFlagModels ( ent , 0 ) ;
2005-04-16 16:21:27 +00:00
else if ( state - > effects & QWEF_FLAG2 )
2004-08-23 00:15:46 +00:00
CL_AddFlagModels ( ent , 1 ) ;
else if ( info - > vweapindex )
2009-07-06 01:20:20 +00:00
CL_AddVWeapModel ( ent , cl . model_precache [ info - > vweapindex ] ) ;
else if ( state - > command . impulse )
CL_AddVWeapModel ( ent , cl . model_precache_vwep [ state - > command . impulse ] ) ;
2004-08-23 00:15:46 +00:00
2009-11-04 21:16:50 +00:00
if ( r_torch . ival )
{
dlight_t * dl ;
dl = CL_NewDlightRGB ( j + 1 , ent - > origin , 300 , r_torch . ival , 0.05 , 0.05 , 0.02 ) ;
dl - > flags | = LFLAG_SHADOWMAP | LFLAG_ALLOW_FLASH ;
dl - > fov = 60 ;
angles [ 0 ] * = 3 ;
angles [ 1 ] + = sin ( realtime ) * 8 ;
angles [ 0 ] + = cos ( realtime * 1.13 ) * 5 ;
AngleVectors ( angles , dl - > axis [ 0 ] , dl - > axis [ 1 ] , dl - > axis [ 2 ] ) ;
}
2004-08-23 00:15:46 +00:00
}
}
2005-02-12 18:56:04 +00:00
void CL_LinkViewModel ( void )
{
entity_t ent ;
2005-09-26 03:40:09 +00:00
static struct model_s * oldmodel [ MAX_SPLITS ] ;
2005-02-12 18:56:04 +00:00
static float lerptime [ MAX_SPLITS ] ;
2009-07-17 22:28:16 +00:00
static float frameduration [ MAX_SPLITS ] ;
2005-02-12 18:56:04 +00:00
static int prevframe [ MAX_SPLITS ] ;
static int oldframe [ MAX_SPLITS ] ;
2006-02-27 00:42:25 +00:00
float alpha ;
2005-02-12 18:56:04 +00:00
2006-05-17 23:01:06 +00:00
extern cvar_t cl_gunx , cl_guny , cl_gunz ;
2006-05-17 23:16:26 +00:00
extern cvar_t cl_gunanglex , cl_gunangley , cl_gunanglez ;
2006-05-17 23:01:06 +00:00
2005-02-12 18:56:04 +00:00
# ifdef SIDEVIEWS
extern qboolean r_secondaryview ;
if ( r_secondaryview = = 1 )
return ;
# endif
2006-01-09 01:49:06 +00:00
if ( r_drawviewmodel . value < = 0 | | ! Cam_DrawViewModel ( r_refdef . currentplayernum ) )
2005-02-12 18:56:04 +00:00
return ;
# ifdef Q2CLIENT
2005-05-26 12:55:34 +00:00
if ( cls . protocol = = CP_QUAKE2 )
2005-02-12 18:56:04 +00:00
return ;
# endif
2009-11-04 21:16:50 +00:00
if ( ! r_drawentities . ival )
2005-02-12 18:56:04 +00:00
return ;
2006-01-09 01:49:06 +00:00
if ( ( cl . stats [ r_refdef . currentplayernum ] [ STAT_ITEMS ] & IT_INVISIBILITY ) & & r_drawviewmodelinvis . value < = 0 )
2005-02-12 18:56:04 +00:00
return ;
if ( cl . stats [ r_refdef . currentplayernum ] [ STAT_HEALTH ] < = 0 )
return ;
memset ( & ent , 0 , sizeof ( ent ) ) ;
ent . model = cl . viewent [ r_refdef . currentplayernum ] . model ;
if ( ! ent . model )
return ;
if ( r_drawviewmodel . value > 0 & & r_drawviewmodel . value < 1 )
2006-02-27 00:42:25 +00:00
alpha = r_drawviewmodel . value ;
2005-02-12 18:56:04 +00:00
else
2006-02-27 00:42:25 +00:00
alpha = 1 ;
2005-02-12 18:56:04 +00:00
2006-01-09 01:49:06 +00:00
if ( ( cl . stats [ r_refdef . currentplayernum ] [ STAT_ITEMS ] & IT_INVISIBILITY )
& & r_drawviewmodelinvis . value > 0
& & r_drawviewmodelinvis . value < 1 )
2006-02-27 00:42:25 +00:00
alpha * = r_drawviewmodelinvis . value ;
2006-05-19 21:00:55 +00:00
# ifdef PEXT_SCALE
ent . scale = 1 ;
# endif
2006-05-17 23:01:06 +00:00
ent . origin [ 0 ] = cl_gunz . value ;
ent . origin [ 1 ] = - cl_gunx . value ;
ent . origin [ 2 ] = - cl_guny . value ;
2006-05-17 23:16:26 +00:00
ent . angles [ 0 ] = cl_gunanglex . value ;
ent . angles [ 1 ] = cl_gunangley . value ;
ent . angles [ 2 ] = cl_gunanglez . value ;
2006-02-27 00:42:25 +00:00
ent . shaderRGBAf [ 0 ] = 1 ;
ent . shaderRGBAf [ 1 ] = 1 ;
ent . shaderRGBAf [ 2 ] = 1 ;
ent . shaderRGBAf [ 3 ] = alpha ;
2006-01-09 01:49:06 +00:00
2009-04-01 22:03:56 +00:00
# ifdef HLCLIENT
if ( ! CLHL_AnimateViewEntity ( & ent ) )
# endif
2005-02-12 18:56:04 +00:00
{
2009-04-01 22:03:56 +00:00
ent . framestate . g [ FS_REG ] . frame [ 0 ] = cl . viewent [ r_refdef . currentplayernum ] . framestate . g [ FS_REG ] . frame [ 0 ] ;
ent . framestate . g [ FS_REG ] . frame [ 1 ] = oldframe [ r_refdef . currentplayernum ] ;
2005-02-12 18:56:04 +00:00
2009-04-01 22:03:56 +00:00
if ( ent . framestate . g [ FS_REG ] . frame [ 0 ] ! = prevframe [ r_refdef . currentplayernum ] )
{
oldframe [ r_refdef . currentplayernum ] = ent . framestate . g [ FS_REG ] . frame [ 1 ] = prevframe [ r_refdef . currentplayernum ] ;
2009-07-17 22:28:16 +00:00
frameduration [ r_refdef . currentplayernum ] = ( realtime - lerptime [ r_refdef . currentplayernum ] ) ;
if ( frameduration [ r_refdef . currentplayernum ] < 0.01 ) //no faster than 100 times a second... to avoid divide by zero
frameduration [ r_refdef . currentplayernum ] = 0.01 ;
if ( frameduration [ r_refdef . currentplayernum ] > 0.2 ) //no slower than 5 times a second
frameduration [ r_refdef . currentplayernum ] = 0.2 ;
2009-04-01 22:03:56 +00:00
lerptime [ r_refdef . currentplayernum ] = realtime ;
}
prevframe [ r_refdef . currentplayernum ] = ent . framestate . g [ FS_REG ] . frame [ 0 ] ;
2006-07-24 04:24:41 +00:00
2009-04-01 22:03:56 +00:00
if ( ent . model ! = oldmodel [ r_refdef . currentplayernum ] )
{
oldmodel [ r_refdef . currentplayernum ] = ent . model ;
oldframe [ r_refdef . currentplayernum ] = ent . framestate . g [ FS_REG ] . frame [ 1 ] = ent . framestate . g [ FS_REG ] . frame [ 0 ] ;
2009-07-17 22:28:16 +00:00
frameduration [ r_refdef . currentplayernum ] = 0.1 ;
2009-04-01 22:03:56 +00:00
lerptime [ r_refdef . currentplayernum ] = realtime ;
}
2009-07-17 22:28:16 +00:00
ent . framestate . g [ FS_REG ] . lerpfrac = 1 - ( realtime - lerptime [ r_refdef . currentplayernum ] ) / frameduration [ r_refdef . currentplayernum ] ;
2009-04-01 22:03:56 +00:00
ent . framestate . g [ FS_REG ] . lerpfrac = bound ( 0 , ent . framestate . g [ FS_REG ] . lerpfrac , 1 ) ;
}
2005-02-12 18:56:04 +00:00
2009-11-04 21:16:50 +00:00
ent . flags = Q2RF_WEAPONMODEL | Q2RF_DEPTHHACK | RF_NOSHADOW ;
2005-02-12 18:56:04 +00:00
V_AddEntity ( & ent ) ;
2005-04-16 16:21:27 +00:00
2009-11-04 21:16:50 +00:00
if ( ! v_powerupshell . ival )
2005-04-16 16:21:27 +00:00
return ;
if ( cl . stats [ r_refdef . currentplayernum ] [ STAT_ITEMS ] & IT_QUAD )
2005-12-08 18:42:08 +00:00
{
2009-11-04 21:16:50 +00:00
if ( v_powerupshell . ival = = 2 )
2005-12-08 18:42:08 +00:00
{
2009-06-21 17:45:33 +00:00
ent . forcedshader = R_RegisterCustom ( " powerups/quadWeapon " , Shader_DefaultSkinShell , NULL ) ;
2005-12-08 18:42:08 +00:00
V_AddEntity ( & ent ) ;
}
else
ent . flags | = Q2RF_SHELL_BLUE ;
}
2005-04-26 16:04:12 +00:00
if ( cl . stats [ r_refdef . currentplayernum ] [ STAT_ITEMS ] & IT_INVULNERABILITY )
2005-12-08 18:42:08 +00:00
{
2009-11-04 21:16:50 +00:00
if ( v_powerupshell . ival = = 2 )
2005-12-08 18:42:08 +00:00
{
2009-06-21 17:45:33 +00:00
ent . forcedshader = R_RegisterCustom ( " powerups/regen " , Shader_DefaultSkinShell , NULL ) ;
2005-12-08 18:42:08 +00:00
ent . fatness = - 2.5 ;
V_AddEntity ( & ent ) ;
}
else
ent . flags | = Q2RF_SHELL_RED ;
}
2005-04-16 16:21:27 +00:00
if ( ! ( ent . flags & ( Q2RF_SHELL_RED | Q2RF_SHELL_GREEN | Q2RF_SHELL_BLUE ) ) )
return ;
ent . fatness = 0.5 ;
2006-02-27 00:42:25 +00:00
ent . shaderRGBAf [ 3 ] / = 10 ;
2009-11-04 21:16:50 +00:00
ent . shaderRGBAf [ 0 ] = ( ! ! ( ent . flags & Q2RF_SHELL_RED ) ) ;
ent . shaderRGBAf [ 1 ] = ( ! ! ( ent . flags & Q2RF_SHELL_GREEN ) ) ;
ent . shaderRGBAf [ 2 ] = ( ! ! ( ent . flags & Q2RF_SHELL_BLUE ) ) ;
ent . forcedshader = R_RegisterCustom ( " q2/shell " , Shader_DefaultSkinShell , NULL ) ;
2005-04-16 16:21:27 +00:00
V_AddEntity ( & ent ) ;
2005-02-12 18:56:04 +00:00
}
2004-08-23 00:15:46 +00:00
//======================================================================
/*
= = = = = = = = = = = = = = =
CL_SetSolid
Builds all the pmove physents for the current frame
= = = = = = = = = = = = = = =
*/
void CL_SetSolidEntities ( void )
{
int i ;
frame_t * frame ;
packet_entities_t * pak ;
entity_state_t * state ;
2009-03-03 01:52:30 +00:00
memset ( & pmove . physents [ 0 ] , 0 , sizeof ( physent_t ) ) ;
2004-08-23 00:15:46 +00:00
pmove . physents [ 0 ] . model = cl . worldmodel ;
2006-05-29 04:50:24 +00:00
VectorClear ( pmove . physents [ 0 ] . origin ) ;
2004-08-23 00:15:46 +00:00
pmove . physents [ 0 ] . info = 0 ;
pmove . numphysent = 1 ;
frame = & cl . frames [ parsecountmod ] ;
pak = & frame - > packet_entities ;
for ( i = 0 ; i < pak - > num_entities ; i + + )
{
state = & pak - > entities [ i ] ;
2006-03-04 20:43:48 +00:00
if ( state - > modelindex < = 0 )
2004-08-23 00:15:46 +00:00
continue ;
if ( ! cl . model_precache [ state - > modelindex ] )
continue ;
if ( * cl . model_precache [ state - > modelindex ] - > name = = ' * ' | | cl . model_precache [ state - > modelindex ] - > numsubmodels )
2005-02-06 02:47:36 +00:00
if ( cl . model_precache [ state - > modelindex ] - > hulls [ 1 ] . firstclipnode
2004-08-23 00:15:46 +00:00
| | cl . model_precache [ state - > modelindex ] - > clipbox )
{
2009-03-03 01:52:30 +00:00
memset ( & pmove . physents [ pmove . numphysent ] , 0 , sizeof ( physent_t ) ) ;
2004-08-23 00:15:46 +00:00
pmove . physents [ pmove . numphysent ] . model = cl . model_precache [ state - > modelindex ] ;
VectorCopy ( state - > origin , pmove . physents [ pmove . numphysent ] . origin ) ;
VectorCopy ( state - > angles , pmove . physents [ pmove . numphysent ] . angles ) ;
2004-09-20 23:25:38 +00:00
pmove . physents [ pmove . numphysent ] . angles [ 0 ] * = - 1 ;
2004-08-23 00:15:46 +00:00
if ( + + pmove . numphysent = = MAX_PHYSENTS )
break ;
}
}
}
/*
= = =
Calculate the new position of players , without other player clipping
We do this to set up real player prediction .
Players are predicted twice , first without clipping other players ,
then with clipping against them .
This sets up the first phase .
= = =
*/
void CL_SetUpPlayerPrediction ( qboolean dopred )
{
int j ;
player_state_t * state ;
player_state_t exact ;
double playertime ;
int msec ;
frame_t * frame ;
struct predicted_player * pplayer ;
extern cvar_t cl_nopred ;
2009-05-24 10:11:17 +00:00
int s ;
2004-08-23 00:15:46 +00:00
playertime = realtime - cls . latency + 0.02 ;
if ( playertime > realtime )
playertime = realtime ;
2009-11-04 21:16:50 +00:00
if ( cl_nopred . value | | cls . demoplayback | | cl . paused )
2004-08-23 00:15:46 +00:00
return ;
frame = & cl . frames [ cl . parsecount & UPDATE_MASK ] ;
2005-02-06 02:47:36 +00:00
for ( j = 0 , pplayer = predicted_players , state = frame - > playerstate ;
2004-08-23 00:15:46 +00:00
j < MAX_CLIENTS ;
2004-10-04 07:26:16 +00:00
j + + , pplayer + + , state + + )
{
2004-08-23 00:15:46 +00:00
pplayer - > active = false ;
if ( state - > messagenum ! = cl . parsecount )
continue ; // not present this frame
if ( ! state - > modelindex )
continue ;
pplayer - > active = true ;
pplayer - > flags = state - > flags ;
2006-04-16 00:34:21 +00:00
/*
2004-08-23 00:15:46 +00:00
if ( pplayer - > frame ! = state - > frame )
{
state - > oldframe = pplayer - > oldframe = pplayer - > frame ;
state - > lerpstarttime = pplayer - > lerptime = realtime ;
pplayer - > frame = state - > frame ;
}
else
{
state - > lerpstarttime = pplayer - > lerptime ;
state - > oldframe = pplayer - > oldframe ;
}
2006-04-16 00:34:21 +00:00
*/
2004-08-23 00:15:46 +00:00
// note that the local player is special, since he moves locally
// we use his last predicted postition
2009-05-24 10:11:17 +00:00
for ( s = 0 ; s < cl . splitclients ; s + + )
2004-10-04 07:26:16 +00:00
{
2009-05-24 10:11:17 +00:00
if ( j = = cl . playernum [ s ] )
{
VectorCopy ( cl . frames [ cls . netchan . outgoing_sequence & UPDATE_MASK ] . playerstate [ cl . playernum [ s ] ] . origin ,
pplayer - > origin ) ;
break ;
}
2004-10-04 07:26:16 +00:00
}
2009-05-24 10:11:17 +00:00
if ( s = = cl . splitclients )
2004-10-04 07:26:16 +00:00
{
2004-08-23 00:15:46 +00:00
// only predict half the move to minimize overruns
msec = 500 * ( playertime - state - > state_time ) ;
if ( msec < = 0 | |
2009-11-04 21:16:50 +00:00
( ! cl_predict_players . ival & & ! cl_predict_players2 . ival ) | |
2004-08-23 00:15:46 +00:00
! dopred )
{
VectorCopy ( state - > origin , pplayer - > origin ) ;
//Con_DPrintf ("nopredict\n");
}
else
{
// predict players movement
if ( msec > 255 )
msec = 255 ;
state - > command . msec = msec ;
//Con_DPrintf ("predict: %i\n", msec);
CL_PredictUsercmd ( 0 , state , & exact , & state - > command ) ;
VectorCopy ( exact . origin , pplayer - > origin ) ;
}
2004-10-04 07:26:16 +00:00
if ( cl . spectator )
{
if ( ! Cam_DrawPlayer ( 0 , j ) )
VectorCopy ( pplayer - > origin , cl . simorg [ 0 ] ) ;
2005-02-06 02:47:36 +00:00
2004-10-04 07:26:16 +00:00
}
2004-08-23 00:15:46 +00:00
}
}
}
/*
= = = = = = = = = = = = = = =
CL_SetSolid
Builds all the pmove physents for the current frame
Note that CL_SetUpPlayerPrediction ( ) must be called first !
pmove must be setup with world and solid entity hulls before calling
( via CL_PredictMove )
= = = = = = = = = = = = = = =
*/
void CL_SetSolidPlayers ( int playernum )
{
int j ;
extern vec3_t player_mins ;
extern vec3_t player_maxs ;
struct predicted_player * pplayer ;
physent_t * pent ;
2009-11-04 21:16:50 +00:00
if ( ! cl_solid_players . ival )
2004-08-23 00:15:46 +00:00
return ;
pent = pmove . physents + pmove . numphysent ;
if ( pmove . numphysent = = MAX_PHYSENTS ) //too many.
return ;
for ( j = 0 , pplayer = predicted_players ; j < MAX_CLIENTS ; j + + , pplayer + + ) {
if ( ! pplayer - > active )
continue ; // not present this frame
// the player object never gets added
if ( j = = playernum )
continue ;
if ( pplayer - > flags & PF_DEAD )
continue ; // dead players aren't solid
2009-03-03 01:52:30 +00:00
memset ( pent , 0 , sizeof ( physent_t ) ) ;
2004-08-23 00:15:46 +00:00
VectorCopy ( pplayer - > origin , pent - > origin ) ;
VectorCopy ( player_mins , pent - > mins ) ;
VectorCopy ( player_maxs , pent - > maxs ) ;
if ( + + pmove . numphysent = = MAX_PHYSENTS ) //we just hit 88 miles per hour.
break ;
pent + + ;
}
}
/*
= = = = = = = = = = = = = = =
CL_EmitEntities
Builds the visedicts array for cl . time
Made up of : clients , packet_entities , nails , and tents
= = = = = = = = = = = = = = =
*/
2005-02-12 18:56:04 +00:00
void CL_SwapEntityLists ( void )
{
cl_oldnumvisedicts = cl_numvisedicts ;
cl_oldvisedicts = cl_visedicts ;
if ( cl_visedicts = = cl_visedicts_list [ 0 ] )
cl_visedicts = cl_visedicts_list [ 1 ] ;
else
cl_visedicts = cl_visedicts_list [ 0 ] ;
// cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1];
// cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1];
cl_numvisedicts = 0 ;
2009-11-04 21:16:50 +00:00
cl_numstrisidx = 0 ;
cl_numstrisvert = 0 ;
cl_numstris = 0 ;
2005-02-12 18:56:04 +00:00
}
2004-08-23 00:15:46 +00:00
void CL_EmitEntities ( void )
{
if ( cls . state ! = ca_active )
return ;
2004-11-27 08:16:25 +00:00
CL_DecayLights ( ) ;
2004-08-23 00:15:46 +00:00
# ifdef Q2CLIENT
2005-05-26 12:55:34 +00:00
if ( cls . protocol = = CP_QUAKE2 )
2004-08-23 00:15:46 +00:00
{
CLQ2_AddEntities ( ) ;
return ;
}
# endif
if ( ! cl . validsequence )
return ;
2005-02-12 18:56:04 +00:00
CL_SwapEntityLists ( ) ;
2004-08-23 00:15:46 +00:00
CL_LinkPlayers ( ) ;
CL_LinkPacketEntities ( ) ;
CL_LinkProjectiles ( ) ;
CL_UpdateTEnts ( ) ;
}
2004-12-08 04:14:52 +00:00
void CL_ParseClientdata ( void ) ;
2004-12-15 17:47:42 +00:00
/*
2004-08-23 00:15:46 +00:00
void MVD_Interpolate ( void )
{
2004-12-08 04:14:52 +00:00
player_state_t * self , * oldself ;
CL_ParseClientdata ( ) ;
self = & cl . frames [ cl . parsecount & UPDATE_MASK ] . playerstate [ cl . playernum [ 0 ] ] ;
oldself = & cl . frames [ ( cls . netchan . outgoing_sequence - 1 ) & UPDATE_MASK ] . playerstate [ cl . playernum [ 0 ] ] ;
self - > messagenum = cl . parsecount ;
VectorCopy ( oldself - > origin , self - > origin ) ;
VectorCopy ( oldself - > velocity , self - > velocity ) ;
VectorCopy ( oldself - > viewangles , self - > viewangles ) ;
2005-02-06 02:47:36 +00:00
2004-08-23 00:15:46 +00:00
cls . netchan . outgoing_sequence = cl . parsecount + 1 ;
}
2004-12-15 17:47:42 +00:00
*/
2004-08-23 00:15:46 +00:00
int mvd_fixangle ;
static float MVD_AdjustAngle ( float current , float ideal , float fraction ) {
float move ;
move = ideal - current ;
if ( move > = 180 )
move - = 360 ;
else if ( move < = - 180 )
move + = 360 ;
return current + fraction * move ;
}
2004-12-15 17:47:42 +00:00
extern float nextdemotime ;
extern float olddemotime ;
static void MVD_InitInterpolation ( void )
{
2004-08-23 00:15:46 +00:00
player_state_t * state , * oldstate ;
int i , tracknum ;
frame_t * frame , * oldframe ;
vec3_t dist ;
struct predicted_player * pplayer ;
2009-05-24 10:11:17 +00:00
int s ;
2004-08-23 00:15:46 +00:00
2004-12-15 17:47:42 +00:00
# define ISDEAD(i) ( (i) >= 41 && (i) <= 102 )
2004-08-23 00:15:46 +00:00
if ( ! cl . validsequence )
return ;
// if (nextdemotime <= olddemotime)
// return;
frame = & cl . frames [ cl . parsecount & UPDATE_MASK ] ;
oldframe = & cl . frames [ ( cl . parsecount - 1 ) & UPDATE_MASK ] ;
// clients
2004-12-15 17:47:42 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
2004-08-23 00:15:46 +00:00
pplayer = & predicted_players [ i ] ;
state = & frame - > playerstate [ i ] ;
oldstate = & oldframe - > playerstate [ i ] ;
2004-12-15 17:47:42 +00:00
if ( pplayer - > predict )
{
2004-08-23 00:15:46 +00:00
VectorCopy ( pplayer - > oldo , oldstate - > origin ) ;
VectorCopy ( pplayer - > olda , oldstate - > command . angles ) ;
VectorCopy ( pplayer - > oldv , oldstate - > velocity ) ;
}
pplayer - > predict = false ;
2004-12-15 17:47:42 +00:00
tracknum = spec_track [ 0 ] ;
if ( ( mvd_fixangle & 1 ) < < i )
{
if ( i = = tracknum )
{
state - > command . angles [ 0 ] = ( state - > viewangles [ 0 ] = cl . viewangles [ 0 ] [ 0 ] ) * 65535 / 360 ;
state - > command . angles [ 1 ] = ( state - > viewangles [ 1 ] = cl . viewangles [ 0 ] [ 1 ] ) * 65535 / 360 ;
state - > command . angles [ 2 ] = ( state - > viewangles [ 2 ] = cl . viewangles [ 0 ] [ 2 ] ) * 65535 / 360 ;
2004-08-23 00:15:46 +00:00
}
// no angle interpolation
VectorCopy ( state - > command . angles , oldstate - > command . angles ) ;
mvd_fixangle & = ~ ( 1 < < i ) ;
}
// we dont interpolate ourself if we are spectating
2009-05-24 10:11:17 +00:00
for ( s = 0 ; s < cl . splitclients ; s + + )
{
if ( i = = cl . playernum [ s ] & & cl . spectator )
break ;
}
if ( s ! = cl . splitclients )
2004-08-23 00:15:46 +00:00
continue ;
memset ( state - > velocity , 0 , sizeof ( state - > velocity ) ) ;
if ( state - > messagenum ! = cl . parsecount )
continue ; // not present this frame
if ( oldstate - > messagenum ! = cl . oldparsecount | | ! oldstate - > messagenum )
continue ; // not present last frame
if ( ! ISDEAD ( state - > frame ) & & ISDEAD ( oldstate - > frame ) )
continue ;
VectorSubtract ( state - > origin , oldstate - > origin , dist ) ;
if ( DotProduct ( dist , dist ) > 22500 )
continue ;
VectorScale ( dist , 1 / ( nextdemotime - olddemotime ) , pplayer - > oldv ) ;
VectorCopy ( state - > origin , pplayer - > oldo ) ;
VectorCopy ( state - > command . angles , pplayer - > olda ) ;
pplayer - > oldstate = oldstate ;
pplayer - > predict = true ;
}
2004-12-15 17:47:42 +00:00
/*
2004-08-23 00:15:46 +00:00
// nails
2004-12-15 17:47:42 +00:00
for ( i = 0 ; i < cl_num_projectiles ; i + + )
{
2004-08-23 00:15:46 +00:00
if ( ! cl . int_projectiles [ i ] . interpolate )
continue ;
VectorCopy ( cl . int_projectiles [ i ] . origin , cl_projectiles [ i ] . origin ) ;
}
2004-12-15 17:47:42 +00:00
*/
2004-08-23 00:15:46 +00:00
}
void MVD_Interpolate ( void )
{
int i , j ;
float f ;
frame_t * frame , * oldframe ;
player_state_t * state , * oldstate , * self , * oldself ;
entity_state_t * oldents ;
struct predicted_player * pplayer ;
static float old ;
2005-12-21 03:07:33 +00:00
extern float demtime ;
2009-05-24 10:11:17 +00:00
int s ;
2004-08-23 00:15:46 +00:00
2009-05-24 10:11:17 +00:00
for ( s = 0 ; s < cl . splitclients ; s + + )
{
self = & cl . frames [ cl . parsecount & UPDATE_MASK ] . playerstate [ cl . playernum [ s ] ] ;
oldself = & cl . frames [ ( cls . netchan . outgoing_sequence - 1 ) & UPDATE_MASK ] . playerstate [ cl . playernum [ s ] ] ;
2004-08-23 00:15:46 +00:00
2009-05-24 10:11:17 +00:00
self - > messagenum = cl . parsecount ;
2004-08-23 00:15:46 +00:00
2009-05-24 10:11:17 +00:00
VectorCopy ( oldself - > origin , self - > origin ) ;
VectorCopy ( oldself - > velocity , self - > velocity ) ;
VectorCopy ( oldself - > viewangles , self - > viewangles ) ;
}
2004-08-23 00:15:46 +00:00
2004-12-15 17:47:42 +00:00
if ( old ! = nextdemotime )
{
2004-08-23 00:15:46 +00:00
old = nextdemotime ;
MVD_InitInterpolation ( ) ;
}
CL_ParseClientdata ( ) ;
cls . netchan . outgoing_sequence = cl . parsecount + 1 ;
if ( ! cl . validsequence )
return ;
if ( nextdemotime < = olddemotime )
return ;
2010-03-14 14:35:56 +00:00
frame = & cl . frames [ cl . validsequence & UPDATE_MASK ] ;
oldframe = & cl . frames [ cl . oldvalidsequence & UPDATE_MASK ] ;
2004-08-23 00:15:46 +00:00
oldents = oldframe - > packet_entities . entities ;
2005-12-21 03:07:33 +00:00
f = ( demtime - olddemotime ) / ( nextdemotime - olddemotime ) ;
2006-07-21 23:38:24 +00:00
f = bound ( 0 , f , 1 ) ;
2004-08-23 00:15:46 +00:00
// interpolate nails
2004-12-15 17:47:42 +00:00
/* for (i = 0; i < cl_num_projectiles; i++)
{
2004-08-23 00:15:46 +00:00
if ( ! cl . int_projectiles [ i ] . interpolate )
continue ;
2004-12-15 17:47:42 +00:00
for ( j = 0 ; j < 3 ; j + + )
{
2004-08-23 00:15:46 +00:00
cl_projectiles [ i ] . origin [ j ] = cl_oldprojectiles [ cl . int_projectiles [ i ] . oldindex ] . origin [ j ] +
f * ( cl . int_projectiles [ i ] . origin [ j ] - cl_oldprojectiles [ cl . int_projectiles [ i ] . oldindex ] . origin [ j ] ) ;
}
}
2004-12-15 17:47:42 +00:00
*/
2004-08-23 00:15:46 +00:00
// interpolate clients
2004-12-15 17:47:42 +00:00
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
2004-08-23 00:15:46 +00:00
pplayer = & predicted_players [ i ] ;
state = & frame - > playerstate [ i ] ;
oldstate = & oldframe - > playerstate [ i ] ;
2004-12-15 17:47:42 +00:00
if ( pplayer - > predict )
{
for ( j = 0 ; j < 3 ; j + + )
{
state - > viewangles [ j ] = MVD_AdjustAngle ( oldstate - > command . angles [ j ] / 65535.0f * 360 , pplayer - > olda [ j ] / 65535.0f * 360 , f ) ;
2004-08-23 00:15:46 +00:00
state - > origin [ j ] = oldstate - > origin [ j ] + f * ( pplayer - > oldo [ j ] - oldstate - > origin [ j ] ) ;
state - > velocity [ j ] = oldstate - > velocity [ j ] + f * ( pplayer - > oldv [ j ] - oldstate - > velocity [ j ] ) ;
}
}
}
}
2004-12-15 17:47:42 +00:00
void CL_ClearPredict ( void )
{
2004-08-23 00:15:46 +00:00
memset ( predicted_players , 0 , sizeof ( predicted_players ) ) ;
mvd_fixangle = 0 ;
}