2008-08-02 22:00:00 +02:00
|
|
|
|
//=======================================================================
|
|
|
|
|
// Copyright XashXT Group 2008 <20>
|
|
|
|
|
// cl_frame.c - client world snapshot
|
|
|
|
|
//=======================================================================
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2008-06-09 22:00:00 +02:00
|
|
|
|
#include "common.h"
|
2007-06-21 22:00:00 +02:00
|
|
|
|
#include "client.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
=========================================================================
|
|
|
|
|
|
|
|
|
|
FRAME PARSING
|
|
|
|
|
|
|
|
|
|
=========================================================================
|
|
|
|
|
*/
|
2008-12-25 22:00:00 +01:00
|
|
|
|
void CL_UpdateEntityFields( edict_t *ent )
|
2008-06-30 22:00:00 +02:00
|
|
|
|
{
|
2009-08-22 22:00:00 +02:00
|
|
|
|
// these fields user can overwrite if need
|
|
|
|
|
ent->v.model = MAKE_STRING( cl.configstrings[CS_MODELS+ent->pvClientData->current.modelindex] );
|
2009-01-03 22:00:00 +01:00
|
|
|
|
|
2010-03-14 22:00:00 +01:00
|
|
|
|
clgame.dllFuncs.pfnUpdateEntityVars( ent, &ent->pvClientData->current, &ent->pvClientData->prev );
|
2009-08-22 22:00:00 +02:00
|
|
|
|
|
2009-11-26 22:00:00 +01:00
|
|
|
|
if( ent->pvClientData->current.ed_flags & ESF_LINKEDICT )
|
|
|
|
|
{
|
|
|
|
|
CL_LinkEdict( ent, false );
|
|
|
|
|
// to avoids multiple relinks when wait for next packet
|
|
|
|
|
ent->pvClientData->current.ed_flags &= ~ESF_LINKEDICT;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-22 22:00:00 +02:00
|
|
|
|
// always keep an actual (users can't replace this)
|
|
|
|
|
ent->serialnumber = ent->pvClientData->current.number;
|
|
|
|
|
ent->v.classname = cl.edict_classnames[ent->pvClientData->current.classname];
|
2008-06-30 22:00:00 +02:00
|
|
|
|
}
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
==================
|
|
|
|
|
CL_DeltaEntity
|
|
|
|
|
|
|
|
|
|
Parses deltas from the given base and adds the resulting entity
|
|
|
|
|
to the current frame
|
|
|
|
|
==================
|
|
|
|
|
*/
|
2008-07-15 22:00:00 +02:00
|
|
|
|
void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t *old, bool unchanged )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2008-12-25 22:00:00 +01:00
|
|
|
|
edict_t *ent;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
entity_state_t *state;
|
2009-11-28 22:00:00 +01:00
|
|
|
|
bool newent = (old) ? false : true;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2008-12-25 22:00:00 +01:00
|
|
|
|
ent = EDICT_NUM( newnum );
|
2009-09-28 22:00:00 +02:00
|
|
|
|
state = &cl.entity_curstates[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
|
2008-07-15 22:00:00 +02:00
|
|
|
|
|
2009-11-28 22:00:00 +01:00
|
|
|
|
if( newent ) old = &clgame.baselines[newnum];
|
|
|
|
|
|
2008-11-14 22:00:00 +01:00
|
|
|
|
if( unchanged ) *state = *old;
|
|
|
|
|
else MSG_ReadDeltaEntity( msg, old, state, newnum );
|
2008-07-15 22:00:00 +02:00
|
|
|
|
|
2009-10-22 22:00:00 +02:00
|
|
|
|
if( state->number == MAX_EDICTS )
|
2009-02-01 22:00:00 +01:00
|
|
|
|
{
|
2010-02-16 22:00:00 +01:00
|
|
|
|
if( newent ) Host_Error( "Cl_DeltaEntity: tried to release new entity\n" );
|
2010-02-02 22:00:00 +01:00
|
|
|
|
if( !ent->free ) CL_FreeEdict( ent );
|
2009-02-01 22:00:00 +01:00
|
|
|
|
return; // entity was delta removed
|
|
|
|
|
}
|
2010-02-02 22:00:00 +01:00
|
|
|
|
|
2007-06-21 22:00:00 +02:00
|
|
|
|
cl.parse_entities++;
|
|
|
|
|
frame->num_entities++;
|
|
|
|
|
|
2009-11-27 22:00:00 +01:00
|
|
|
|
if( ent->free ) CL_InitEdict( ent );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2009-09-28 22:00:00 +02:00
|
|
|
|
// some data changes will force no lerping
|
|
|
|
|
if( state->ed_flags & ESF_NODELTA ) ent->pvClientData->serverframe = -99;
|
2009-11-28 22:00:00 +01:00
|
|
|
|
if( newent ) state->ed_flags |= ESF_LINKEDICT; // need to relink
|
2009-09-28 22:00:00 +02:00
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
if( ent->pvClientData->serverframe != cl.frame.serverframe - 1 )
|
2008-06-30 22:00:00 +02:00
|
|
|
|
{
|
2007-06-21 22:00:00 +02:00
|
|
|
|
// duplicate the current state so lerping doesn't hurt anything
|
2008-12-26 22:00:00 +01:00
|
|
|
|
ent->pvClientData->prev = *state;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ // shuffle the last state to previous
|
2008-12-26 22:00:00 +01:00
|
|
|
|
ent->pvClientData->prev = ent->pvClientData->current;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
ent->pvClientData->serverframe = cl.frame.serverframe;
|
2008-12-26 22:00:00 +01:00
|
|
|
|
ent->pvClientData->current = *state;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
==================
|
|
|
|
|
CL_ParsePacketEntities
|
|
|
|
|
|
|
|
|
|
An svc_packetentities has just been parsed, deal with the
|
|
|
|
|
rest of the data stream.
|
|
|
|
|
==================
|
|
|
|
|
*/
|
2008-05-20 22:00:00 +02:00
|
|
|
|
void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newframe )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2008-05-20 22:00:00 +02:00
|
|
|
|
int newnum;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
entity_state_t *oldstate;
|
2008-05-20 22:00:00 +02:00
|
|
|
|
int oldindex, oldnum;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
newframe->parse_entities = cl.parse_entities;
|
|
|
|
|
newframe->num_entities = 0;
|
|
|
|
|
|
|
|
|
|
// delta from the entities present in oldframe
|
|
|
|
|
oldindex = 0;
|
2008-07-15 22:00:00 +02:00
|
|
|
|
oldstate = NULL;
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( !oldframe ) oldnum = MAX_ENTNUMBER;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldindex >= oldframe->num_entities )
|
|
|
|
|
{
|
|
|
|
|
oldnum = MAX_ENTNUMBER;
|
|
|
|
|
}
|
2007-06-21 22:00:00 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldnum = oldstate->number;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-30 22:00:00 +02:00
|
|
|
|
while( 1 )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2008-07-15 22:00:00 +02:00
|
|
|
|
// read the entity index number
|
|
|
|
|
newnum = MSG_ReadShort( msg );
|
2008-08-11 22:00:00 +02:00
|
|
|
|
if( !newnum ) break; // end of packet entities
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2009-06-24 22:00:00 +02:00
|
|
|
|
if( msg->error )
|
2008-07-15 22:00:00 +02:00
|
|
|
|
Host_Error("CL_ParsePacketEntities: end of message[%d > %d]\n", msg->readcount, msg->cursize );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2009-11-27 22:00:00 +01:00
|
|
|
|
while( newnum >= clgame.globals->numEntities )
|
|
|
|
|
clgame.globals->numEntities++;
|
2009-01-04 22:00:00 +01:00
|
|
|
|
|
2008-07-15 22:00:00 +02:00
|
|
|
|
while( oldnum < newnum )
|
2007-09-10 22:00:00 +02:00
|
|
|
|
{
|
|
|
|
|
// one or more entities from the old packet are unchanged
|
2008-07-15 22:00:00 +02:00
|
|
|
|
CL_DeltaEntity( msg, newframe, oldnum, oldstate, true );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
oldindex++;
|
|
|
|
|
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldindex >= oldframe->num_entities )
|
|
|
|
|
{
|
|
|
|
|
oldnum = MAX_ENTNUMBER;
|
|
|
|
|
}
|
2007-06-21 22:00:00 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldnum = oldstate->number;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldnum == newnum )
|
|
|
|
|
{
|
|
|
|
|
// delta from previous state
|
2008-07-15 22:00:00 +02:00
|
|
|
|
CL_DeltaEntity( msg, newframe, newnum, oldstate, false );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldindex++;
|
|
|
|
|
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldindex >= oldframe->num_entities )
|
|
|
|
|
{
|
|
|
|
|
oldnum = MAX_ENTNUMBER;
|
|
|
|
|
}
|
2007-06-21 22:00:00 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldnum = oldstate->number;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldnum > newnum )
|
2008-05-20 22:00:00 +02:00
|
|
|
|
{
|
2009-01-04 22:00:00 +01:00
|
|
|
|
// delta from baseline ?
|
2009-11-28 22:00:00 +01:00
|
|
|
|
CL_DeltaEntity( msg, newframe, newnum, NULL, false );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// any remaining entities in the old frame are copied over
|
2008-06-30 22:00:00 +02:00
|
|
|
|
while( oldnum != MAX_ENTNUMBER )
|
|
|
|
|
{
|
|
|
|
|
// one or more entities from the old packet are unchanged
|
2008-07-15 22:00:00 +02:00
|
|
|
|
CL_DeltaEntity( msg, newframe, oldnum, oldstate, true );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldindex++;
|
|
|
|
|
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( oldindex >= oldframe->num_entities )
|
|
|
|
|
{
|
|
|
|
|
oldnum = MAX_ENTNUMBER;
|
|
|
|
|
}
|
2007-06-21 22:00:00 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
oldstate = &cl.entity_curstates[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
|
2007-06-21 22:00:00 +02:00
|
|
|
|
oldnum = oldstate->number;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-03 22:00:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
2007-06-21 22:00:00 +02:00
|
|
|
|
/*
|
|
|
|
|
================
|
|
|
|
|
CL_ParseFrame
|
|
|
|
|
================
|
|
|
|
|
*/
|
2008-05-20 22:00:00 +02:00
|
|
|
|
void CL_ParseFrame( sizebuf_t *msg )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2010-03-28 22:00:00 +02:00
|
|
|
|
int cmd, len, client_idx;
|
2009-12-04 22:00:00 +01:00
|
|
|
|
edict_t *clent;
|
2008-07-12 22:00:00 +02:00
|
|
|
|
|
2009-07-04 22:00:00 +02:00
|
|
|
|
Mem_Set( &cl.frame, 0, sizeof( cl.frame ));
|
2009-06-24 22:00:00 +02:00
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
cl.frame.serverframe = MSG_ReadLong( msg );
|
2009-09-28 22:00:00 +02:00
|
|
|
|
cl.frame.servertime = MSG_ReadLong( msg );
|
2009-09-17 22:00:00 +02:00
|
|
|
|
cl.serverframetime = MSG_ReadLong( msg );
|
2009-09-16 22:00:00 +02:00
|
|
|
|
cl.frame.deltaframe = MSG_ReadLong( msg );
|
|
|
|
|
cl.surpressCount = MSG_ReadByte( msg );
|
2010-03-28 22:00:00 +02:00
|
|
|
|
client_idx = MSG_ReadByte( msg );
|
|
|
|
|
|
|
|
|
|
// read clientindex
|
|
|
|
|
clent = EDICT_NUM( client_idx ); // get client
|
|
|
|
|
if(( client_idx - 1 ) != cl.playernum )
|
|
|
|
|
Host_Error( "CL_ParseFrame: invalid playernum (%d should be %d)\n", client_idx - 1, cl.playernum );
|
2009-11-25 22:00:00 +01:00
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
// If the frame is delta compressed from data that we
|
|
|
|
|
// no longer have available, we must suck up the rest of
|
|
|
|
|
// the frame, but not use it, then ask for a non-compressed
|
|
|
|
|
// message
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( cl.frame.deltaframe <= 0 )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2008-06-30 22:00:00 +02:00
|
|
|
|
cl.frame.valid = true; // uncompressed frame
|
2007-06-21 22:00:00 +02:00
|
|
|
|
cls.demowaiting = false; // we can start recording now
|
2009-09-15 22:00:00 +02:00
|
|
|
|
cl.oldframe = NULL;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2010-04-02 22:00:00 +02:00
|
|
|
|
cl.oldframe = &cl.frames[cl.frame.deltaframe & CL_UPDATE_MASK];
|
2009-09-15 22:00:00 +02:00
|
|
|
|
if( !cl.oldframe->valid )
|
2007-10-29 22:00:00 +01:00
|
|
|
|
{
|
|
|
|
|
// should never happen
|
2010-01-31 22:00:00 +01:00
|
|
|
|
MsgDev( D_INFO, "delta from invalid frame (not supposed to happen!)\n" );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2009-09-16 22:00:00 +02:00
|
|
|
|
if( cl.oldframe->serverframe != cl.frame.deltaframe )
|
2007-10-19 22:00:00 +02:00
|
|
|
|
{
|
|
|
|
|
// The frame that the server did the delta from
|
2007-06-21 22:00:00 +02:00
|
|
|
|
// is too old, so we can't reconstruct it properly.
|
2010-01-31 22:00:00 +01:00
|
|
|
|
MsgDev( D_INFO, "delta frame too old\n" );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2009-09-15 22:00:00 +02:00
|
|
|
|
else if( cl.parse_entities - cl.oldframe->parse_entities > MAX_PARSE_ENTITIES - 128 )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2010-01-31 22:00:00 +01:00
|
|
|
|
MsgDev( D_INFO, "delta parse_entities too old\n" );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2007-10-19 22:00:00 +02:00
|
|
|
|
else cl.frame.valid = true; // valid delta parse
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read areabits
|
2008-06-30 22:00:00 +02:00
|
|
|
|
len = MSG_ReadByte( msg );
|
|
|
|
|
MSG_ReadData( msg, &cl.frame.areabits, len );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
|
2009-09-28 22:00:00 +02:00
|
|
|
|
// read packet entities
|
|
|
|
|
cmd = MSG_ReadByte( msg );
|
|
|
|
|
if( cmd != svc_packetentities ) Host_Error("CL_ParseFrame: not packetentities[%d]\n", cmd );
|
|
|
|
|
CL_ParsePacketEntities( msg, cl.oldframe, &cl.frame );
|
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
// save the frame off in the backup array for later delta comparisons
|
2010-04-02 22:00:00 +02:00
|
|
|
|
cl.frames[cl.frame.serverframe & CL_UPDATE_MASK] = cl.frame;
|
2009-09-15 22:00:00 +02:00
|
|
|
|
|
2010-02-10 22:00:00 +01:00
|
|
|
|
if( !cl.frame.valid ) return;
|
|
|
|
|
|
|
|
|
|
if( cls.state != ca_active )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2010-02-10 22:00:00 +01:00
|
|
|
|
edict_t *player;
|
2009-11-26 22:00:00 +01:00
|
|
|
|
|
2010-02-10 22:00:00 +01:00
|
|
|
|
// client entered the game
|
|
|
|
|
cls.state = ca_active;
|
|
|
|
|
cl.force_refdef = true;
|
2010-03-28 22:00:00 +02:00
|
|
|
|
cls.drawplaque = true;
|
2009-09-28 22:00:00 +02:00
|
|
|
|
|
2010-02-10 22:00:00 +01:00
|
|
|
|
player = CL_GetLocalPlayer();
|
|
|
|
|
SCR_MakeLevelShot(); // make levelshot if needs
|
2009-10-18 22:00:00 +02:00
|
|
|
|
|
2010-02-10 22:00:00 +01:00
|
|
|
|
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
|
|
|
|
// getting a valid frame message ends the connection process
|
|
|
|
|
VectorCopy( player->pvClientData->current.origin, cl.predicted_origin );
|
|
|
|
|
VectorCopy( player->v.viewangles, cl.predicted_angles );
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2010-02-10 22:00:00 +01:00
|
|
|
|
|
|
|
|
|
CL_CheckPredictionError();
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
==========================================================================
|
|
|
|
|
|
|
|
|
|
INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
|
|
|
|
|
|
|
|
|
|
==========================================================================
|
|
|
|
|
*/
|
|
|
|
|
/*
|
|
|
|
|
===============
|
|
|
|
|
CL_AddPacketEntities
|
|
|
|
|
|
|
|
|
|
===============
|
|
|
|
|
*/
|
2008-06-30 22:00:00 +02:00
|
|
|
|
void CL_AddPacketEntities( frame_t *frame )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
edict_t *ent;
|
|
|
|
|
int e, ed_type;
|
2009-09-16 22:00:00 +02:00
|
|
|
|
|
2009-11-27 22:00:00 +01:00
|
|
|
|
// now recalc actual entcount
|
|
|
|
|
for( ; EDICT_NUM( clgame.globals->numEntities - 1 )->free; clgame.globals->numEntities-- );
|
|
|
|
|
|
2009-11-26 22:00:00 +01:00
|
|
|
|
for( e = 1; e < clgame.globals->numEntities; e++ )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2009-11-26 22:00:00 +01:00
|
|
|
|
ent = CL_GetEdictByIndex( e );
|
|
|
|
|
if( !CL_IsValidEdict( ent )) continue;
|
2009-09-17 22:00:00 +02:00
|
|
|
|
|
2009-09-28 22:00:00 +02:00
|
|
|
|
ed_type = ent->pvClientData->current.ed_type;
|
2009-09-17 22:00:00 +02:00
|
|
|
|
CL_UpdateEntityFields( ent );
|
|
|
|
|
|
2010-03-14 22:00:00 +01:00
|
|
|
|
if( clgame.dllFuncs.pfnAddVisibleEntity( ent, ed_type ))
|
2009-07-15 22:00:00 +02:00
|
|
|
|
{
|
2009-09-28 22:00:00 +02:00
|
|
|
|
if( ed_type == ED_PORTAL && !VectorCompare( ent->v.origin, ent->v.oldorigin ))
|
2009-07-28 22:00:00 +02:00
|
|
|
|
cl.render_flags |= RDF_PORTALINVIEW;
|
2009-07-15 22:00:00 +02:00
|
|
|
|
}
|
2009-07-19 22:00:00 +02:00
|
|
|
|
// NOTE: skyportal entity never added to rendering
|
2009-09-28 22:00:00 +02:00
|
|
|
|
if( ed_type == ED_SKYPORTAL ) cl.render_flags |= RDF_SKYPORTALINVIEW;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2009-09-16 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
if( cl.oldframe && !memcmp( cl.oldframe->areabits, cl.frame.areabits, sizeof( cl.frame.areabits )))
|
|
|
|
|
cl.render_flags |= RDF_OLDAREABITS;
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
===============
|
|
|
|
|
CL_AddEntities
|
|
|
|
|
|
|
|
|
|
Emits all entities, particles, and lights to the refresh
|
|
|
|
|
===============
|
|
|
|
|
*/
|
2008-06-30 22:00:00 +02:00
|
|
|
|
void CL_AddEntities( void )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
{
|
2008-06-30 22:00:00 +02:00
|
|
|
|
if( cls.state != ca_active )
|
2007-06-21 22:00:00 +02:00
|
|
|
|
return;
|
|
|
|
|
|
2009-09-16 22:00:00 +02:00
|
|
|
|
cl.render_flags = 0;
|
|
|
|
|
|
2010-03-09 22:00:00 +01:00
|
|
|
|
clgame.dllFuncs.pfnStartFrame(); // new frame has begin
|
2008-06-30 22:00:00 +02:00
|
|
|
|
CL_AddPacketEntities( &cl.frame );
|
2009-06-24 22:00:00 +02:00
|
|
|
|
clgame.dllFuncs.pfnCreateEntities();
|
2009-01-22 22:00:00 +01:00
|
|
|
|
|
2010-02-23 22:00:00 +01:00
|
|
|
|
CL_FireEvents(); // so tempents can be created immediately
|
2008-06-30 22:00:00 +02:00
|
|
|
|
CL_AddParticles();
|
|
|
|
|
CL_AddDLights();
|
|
|
|
|
CL_AddLightStyles();
|
2008-11-27 22:00:00 +01:00
|
|
|
|
CL_AddDecals();
|
2009-01-22 22:00:00 +01:00
|
|
|
|
|
|
|
|
|
// perfomance test
|
|
|
|
|
CL_TestEntities();
|
|
|
|
|
CL_TestLights();
|
2007-06-21 22:00:00 +02:00
|
|
|
|
}
|
2008-06-12 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// sound engine implementation
|
|
|
|
|
//
|
2010-04-21 22:00:00 +02:00
|
|
|
|
bool CL_GetEntitySpatialization( int entnum, soundinfo_t *info )
|
|
|
|
|
{
|
|
|
|
|
edict_t *pSound;
|
|
|
|
|
|
|
|
|
|
// world is always audible
|
|
|
|
|
if( entnum == 0 )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if( entnum < 0 || entnum >= GI->max_edicts )
|
|
|
|
|
{
|
|
|
|
|
MsgDev( D_ERROR, "CL_GetEntitySoundSpatialization: invalid entnum %d\n", entnum );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// while explosion entity can be died before sound played completely
|
|
|
|
|
if( entnum >= clgame.globals->numEntities )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
pSound = CL_GetEdictByIndex( entnum );
|
|
|
|
|
|
|
|
|
|
// out of PVS, removed etc
|
|
|
|
|
if( !pSound ) return false;
|
|
|
|
|
|
|
|
|
|
if( !pSound->v.modelindex )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if( info->pflRadius )
|
|
|
|
|
{
|
|
|
|
|
vec3_t mins, maxs;
|
|
|
|
|
|
|
|
|
|
Mod_GetBounds( pSound->v.modelindex, mins, maxs );
|
|
|
|
|
*info->pflRadius = RadiusFromBounds( mins, maxs );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( info->pOrigin )
|
|
|
|
|
{
|
|
|
|
|
VectorCopy( pSound->v.origin, info->pOrigin );
|
|
|
|
|
|
|
|
|
|
if( CM_GetModelType( pSound->v.modelindex ) == mod_brush )
|
|
|
|
|
{
|
|
|
|
|
vec3_t mins, maxs, center;
|
|
|
|
|
|
|
|
|
|
Mod_GetBounds( pSound->v.modelindex, mins, maxs );
|
|
|
|
|
VectorAverage( mins, maxs, center );
|
|
|
|
|
VectorAdd( info->pOrigin, center, info->pOrigin );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( info->pAngles )
|
|
|
|
|
{
|
|
|
|
|
VectorCopy( pSound->v.angles, info->pAngles );
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-01 22:00:00 +02:00
|
|
|
|
void CL_GetEntitySoundSpatialization( int entnum, vec3_t origin, vec3_t velocity )
|
2008-06-12 22:00:00 +02:00
|
|
|
|
{
|
2009-10-29 22:00:00 +01:00
|
|
|
|
edict_t *ent;
|
|
|
|
|
vec3_t mins, maxs, midPoint;
|
2008-06-12 22:00:00 +02:00
|
|
|
|
|
2009-09-24 22:00:00 +02:00
|
|
|
|
if( entnum < 0 || entnum >= GI->max_edicts )
|
2008-06-12 22:00:00 +02:00
|
|
|
|
{
|
2008-07-01 22:00:00 +02:00
|
|
|
|
MsgDev( D_ERROR, "CL_GetEntitySoundSpatialization: invalid entnum %d\n", entnum );
|
2008-06-12 22:00:00 +02:00
|
|
|
|
VectorCopy( vec3_origin, origin );
|
|
|
|
|
VectorCopy( vec3_origin, velocity );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-28 22:00:00 +01:00
|
|
|
|
// while explosion entity can be died before sound played completely
|
|
|
|
|
if( entnum >= clgame.globals->numEntities ) return;
|
|
|
|
|
|
2009-10-18 22:00:00 +02:00
|
|
|
|
ent = CL_GetEdictByIndex( entnum );
|
2009-11-26 22:00:00 +01:00
|
|
|
|
if( !CL_IsValidEdict( ent )) return; // leave uncahnged
|
2008-06-12 22:00:00 +02:00
|
|
|
|
|
2009-09-17 22:00:00 +02:00
|
|
|
|
// setup origin and velocity
|
|
|
|
|
VectorCopy( ent->v.origin, origin );
|
2009-09-28 22:00:00 +02:00
|
|
|
|
VectorCopy( ent->v.velocity, velocity );
|
2008-06-12 22:00:00 +02:00
|
|
|
|
|
|
|
|
|
// if a brush model, offset the origin
|
2010-02-28 22:00:00 +01:00
|
|
|
|
if( CM_GetModelType( ent->v.modelindex ) == mod_brush )
|
2008-06-12 22:00:00 +02:00
|
|
|
|
{
|
2009-10-29 22:00:00 +01:00
|
|
|
|
Mod_GetBounds( ent->v.modelindex, mins, maxs );
|
2009-10-28 22:00:00 +01:00
|
|
|
|
VectorAverage( mins, maxs, midPoint );
|
2008-07-16 22:00:00 +02:00
|
|
|
|
VectorAdd( origin, midPoint, origin );
|
2008-06-12 22:00:00 +02:00
|
|
|
|
}
|
|
|
|
|
}
|