/sp/src/game/client/c_baseentity.cpp
C++ | 6487 lines | 4249 code | 1056 blank | 1182 comment | 733 complexity | ec902e6dc467d7e0e59ce71e46a3782c MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- //========= Copyright Valve Corporation, All rights reserved. ============//
- //
- // Purpose:
- //
- // $NoKeywords: $
- //===========================================================================//
- #include "cbase.h"
- #include "c_baseentity.h"
- #include "prediction.h"
- #include "model_types.h"
- #include "iviewrender_beams.h"
- #include "dlight.h"
- #include "iviewrender.h"
- #include "view.h"
- #include "iefx.h"
- #include "c_team.h"
- #include "clientmode.h"
- #include "usercmd.h"
- #include "engine/IEngineSound.h"
- #include "engine/IEngineTrace.h"
- #include "engine/ivmodelinfo.h"
- #include "tier0/vprof.h"
- #include "fx_line.h"
- #include "interface.h"
- #include "materialsystem/imaterialsystem.h"
- #include "soundinfo.h"
- #include "mathlib/vmatrix.h"
- #include "isaverestore.h"
- #include "interval.h"
- #include "engine/ivdebugoverlay.h"
- #include "c_ai_basenpc.h"
- #include "apparent_velocity_helper.h"
- #include "c_baseanimatingoverlay.h"
- #include "tier1/KeyValues.h"
- #include "hltvcamera.h"
- #include "datacache/imdlcache.h"
- #include "toolframework/itoolframework.h"
- #include "toolframework_client.h"
- #include "decals.h"
- #include "cdll_bounded_cvars.h"
- #include "inetchannelinfo.h"
- #include "proto_version.h"
- // memdbgon must be the last include file in a .cpp file!!!
- #include "tier0/memdbgon.h"
- #ifdef INTERPOLATEDVAR_PARANOID_MEASUREMENT
- int g_nInterpolatedVarsChanged = 0;
- bool g_bRestoreInterpolatedVarValues = false;
- #endif
- static bool g_bWasSkipping = (bool)-1;
- static bool g_bWasThreaded =(bool)-1;
- static int g_nThreadModeTicks = 0;
- void cc_cl_interp_all_changed( IConVar *pConVar, const char *pOldString, float flOldValue )
- {
- ConVarRef var( pConVar );
- if ( var.GetInt() )
- {
- C_BaseEntityIterator iterator;
- C_BaseEntity *pEnt;
- while ( (pEnt = iterator.Next()) != NULL )
- {
- if ( pEnt->ShouldInterpolate() )
- {
- pEnt->AddToInterpolationList();
- }
- }
- }
- }
- static ConVar cl_extrapolate( "cl_extrapolate", "1", FCVAR_CHEAT, "Enable/disable extrapolation if interpolation history runs out." );
- static ConVar cl_interp_npcs( "cl_interp_npcs", "0.0", FCVAR_USERINFO, "Interpolate NPC positions starting this many seconds in past (or cl_interp, if greater)" );
- static ConVar cl_interp_all( "cl_interp_all", "0", 0, "Disable interpolation list optimizations.", 0, 0, 0, 0, cc_cl_interp_all_changed );
- ConVar r_drawmodeldecals( "r_drawmodeldecals", "1" );
- extern ConVar cl_showerror;
- int C_BaseEntity::m_nPredictionRandomSeed = -1;
- C_BasePlayer *C_BaseEntity::m_pPredictionPlayer = NULL;
- bool C_BaseEntity::s_bAbsQueriesValid = true;
- bool C_BaseEntity::s_bAbsRecomputationEnabled = true;
- bool C_BaseEntity::s_bInterpolate = true;
- bool C_BaseEntity::sm_bDisableTouchFuncs = false; // Disables PhysicsTouch and PhysicsStartTouch function calls
- static ConVar r_drawrenderboxes( "r_drawrenderboxes", "0", FCVAR_CHEAT );
- static bool g_bAbsRecomputationStack[8];
- static unsigned short g_iAbsRecomputationStackPos = 0;
- // All the entities that want Interpolate() called on them.
- static CUtlLinkedList<C_BaseEntity*, unsigned short> g_InterpolationList;
- static CUtlLinkedList<C_BaseEntity*, unsigned short> g_TeleportList;
- #if !defined( NO_ENTITY_PREDICTION )
- //-----------------------------------------------------------------------------
- // Purpose: Maintains a list of predicted or client created entities
- //-----------------------------------------------------------------------------
- class CPredictableList : public IPredictableList
- {
- public:
- virtual C_BaseEntity *GetPredictable( int slot );
- virtual int GetPredictableCount( void );
- protected:
- void AddToPredictableList( ClientEntityHandle_t add );
- void RemoveFromPredictablesList( ClientEntityHandle_t remove );
- private:
- CUtlVector< ClientEntityHandle_t > m_Predictables;
- friend class C_BaseEntity;
- };
- // Create singleton
- static CPredictableList g_Predictables;
- IPredictableList *predictables = &g_Predictables;
- //-----------------------------------------------------------------------------
- // Purpose: Add entity to list
- // Input : add -
- // Output : int
- //-----------------------------------------------------------------------------
- void CPredictableList::AddToPredictableList( ClientEntityHandle_t add )
- {
- // This is a hack to remap slot to index
- if ( m_Predictables.Find( add ) != m_Predictables.InvalidIndex() )
- {
- return;
- }
- // Add to general list
- m_Predictables.AddToTail( add );
- // Maintain sort order by entindex
- int count = m_Predictables.Size();
- if ( count < 2 )
- return;
- int i, j;
- for ( i = 0; i < count; i++ )
- {
- for ( j = i + 1; j < count; j++ )
- {
- ClientEntityHandle_t h1 = m_Predictables[ i ];
- ClientEntityHandle_t h2 = m_Predictables[ j ];
- C_BaseEntity *p1 = cl_entitylist->GetBaseEntityFromHandle( h1 );
- C_BaseEntity *p2 = cl_entitylist->GetBaseEntityFromHandle( h2 );
- if ( !p1 || !p2 )
- {
- Assert( 0 );
- continue;
- }
- if ( p1->entindex() != -1 &&
- p2->entindex() != -1 )
- {
- if ( p1->entindex() < p2->entindex() )
- continue;
- }
- if ( p2->entindex() == -1 )
- continue;
- m_Predictables[ i ] = h2;
- m_Predictables[ j ] = h1;
- }
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : remove -
- //-----------------------------------------------------------------------------
- void CPredictableList::RemoveFromPredictablesList( ClientEntityHandle_t remove )
- {
- m_Predictables.FindAndRemove( remove );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : slot -
- // Output : C_BaseEntity
- //-----------------------------------------------------------------------------
- C_BaseEntity *CPredictableList::GetPredictable( int slot )
- {
- return cl_entitylist->GetBaseEntityFromHandle( m_Predictables[ slot ] );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Output : int
- //-----------------------------------------------------------------------------
- int CPredictableList::GetPredictableCount( void )
- {
- return m_Predictables.Count();
- }
- //-----------------------------------------------------------------------------
- // Purpose: Searc predictables for previously created entity (by testId)
- // Input : testId -
- // Output : static C_BaseEntity
- //-----------------------------------------------------------------------------
- static C_BaseEntity *FindPreviouslyCreatedEntity( CPredictableId& testId )
- {
- int c = predictables->GetPredictableCount();
- int i;
- for ( i = 0; i < c; i++ )
- {
- C_BaseEntity *e = predictables->GetPredictable( i );
- if ( !e || !e->IsClientCreated() )
- continue;
- // Found it, note use of operator ==
- if ( testId == e->m_PredictableID )
- {
- return e;
- }
- }
- return NULL;
- }
- #endif
- abstract_class IRecordingList
- {
- public:
- virtual ~IRecordingList() {};
- virtual void AddToList( ClientEntityHandle_t add ) = 0;
- virtual void RemoveFromList( ClientEntityHandle_t remove ) = 0;
- virtual int Count() = 0;
- virtual IClientRenderable *Get( int index ) = 0;
- };
- class CRecordingList : public IRecordingList
- {
- public:
- virtual void AddToList( ClientEntityHandle_t add );
- virtual void RemoveFromList( ClientEntityHandle_t remove );
- virtual int Count();
- IClientRenderable *Get( int index );
- private:
- CUtlVector< ClientEntityHandle_t > m_Recording;
- };
- static CRecordingList g_RecordingList;
- IRecordingList *recordinglist = &g_RecordingList;
- //-----------------------------------------------------------------------------
- // Purpose: Add entity to list
- // Input : add -
- // Output : int
- //-----------------------------------------------------------------------------
- void CRecordingList::AddToList( ClientEntityHandle_t add )
- {
- // This is a hack to remap slot to index
- if ( m_Recording.Find( add ) != m_Recording.InvalidIndex() )
- {
- return;
- }
- // Add to general list
- m_Recording.AddToTail( add );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : remove -
- //-----------------------------------------------------------------------------
- void CRecordingList::RemoveFromList( ClientEntityHandle_t remove )
- {
- m_Recording.FindAndRemove( remove );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : slot -
- // Output : IClientRenderable
- //-----------------------------------------------------------------------------
- IClientRenderable *CRecordingList::Get( int index )
- {
- return cl_entitylist->GetClientRenderableFromHandle( m_Recording[ index ] );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Output : int
- //-----------------------------------------------------------------------------
- int CRecordingList::Count()
- {
- return m_Recording.Count();
- }
- // Should these be somewhere else?
- #define PITCH 0
- //-----------------------------------------------------------------------------
- // Purpose: Decodes animtime and notes when it changes
- // Input : *pStruct - ( C_BaseEntity * ) used to flag animtime is changine
- // *pVarData -
- // *pIn -
- // objectID -
- //-----------------------------------------------------------------------------
- void RecvProxy_AnimTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- C_BaseEntity *pEntity = ( C_BaseEntity * )pStruct;
- Assert( pOut == &pEntity->m_flAnimTime );
- int t;
- int tickbase;
- int addt;
- // Unpack the data.
- addt = pData->m_Value.m_Int;
- // Note, this needs to be encoded relative to packet timestamp, not raw client clock
- tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() );
- t = tickbase;
- // and then go back to floating point time.
- t += addt; // Add in an additional up to 256 100ths from the server
- // center m_flAnimTime around current time.
- while (t < gpGlobals->tickcount - 127)
- t += 256;
- while (t > gpGlobals->tickcount + 127)
- t -= 256;
-
- pEntity->m_flAnimTime = ( t * TICK_INTERVAL );
- }
- void RecvProxy_SimulationTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- C_BaseEntity *pEntity = ( C_BaseEntity * )pStruct;
- Assert( pOut == &pEntity->m_flSimulationTime );
- int t;
- int tickbase;
- int addt;
- // Unpack the data.
- addt = pData->m_Value.m_Int;
- // Note, this needs to be encoded relative to packet timestamp, not raw client clock
- tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() );
- t = tickbase;
- // and then go back to floating point time.
- t += addt; // Add in an additional up to 256 100ths from the server
- // center m_flSimulationTime around current time.
- while (t < gpGlobals->tickcount - 127)
- t += 256;
- while (t > gpGlobals->tickcount + 127)
- t -= 256;
-
- pEntity->m_flSimulationTime = ( t * TICK_INTERVAL );
- }
- void RecvProxy_LocalVelocity( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- CBaseEntity *pEnt = (CBaseEntity *)pStruct;
- Vector vecVelocity;
-
- vecVelocity.x = pData->m_Value.m_Vector[0];
- vecVelocity.y = pData->m_Value.m_Vector[1];
- vecVelocity.z = pData->m_Value.m_Vector[2];
- // SetLocalVelocity checks to see if the value has changed
- pEnt->SetLocalVelocity( vecVelocity );
- }
- void RecvProxy_ToolRecording( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- if ( !ToolsEnabled() )
- return;
- CBaseEntity *pEnt = (CBaseEntity *)pStruct;
- pEnt->SetToolRecording( pData->m_Value.m_Int != 0 );
- }
- // Expose it to the engine.
- IMPLEMENT_CLIENTCLASS(C_BaseEntity, DT_BaseEntity, CBaseEntity);
- static void RecvProxy_MoveType( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- ((C_BaseEntity*)pStruct)->SetMoveType( (MoveType_t)(pData->m_Value.m_Int) );
- }
- static void RecvProxy_MoveCollide( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- ((C_BaseEntity*)pStruct)->SetMoveCollide( (MoveCollide_t)(pData->m_Value.m_Int) );
- }
- static void RecvProxy_Solid( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- ((C_BaseEntity*)pStruct)->SetSolid( (SolidType_t)pData->m_Value.m_Int );
- }
- static void RecvProxy_SolidFlags( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- ((C_BaseEntity*)pStruct)->SetSolidFlags( pData->m_Value.m_Int );
- }
- void RecvProxy_EffectFlags( const CRecvProxyData *pData, void *pStruct, void *pOut )
- {
- ((C_BaseEntity*)pStruct)->SetEffects( pData->m_Value.m_Int );
- }
- BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
- RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
- END_RECV_TABLE()
- #ifndef NO_ENTITY_PREDICTION
- BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_PredictableId )
- RecvPropPredictableId( RECVINFO( m_PredictableID ) ),
- RecvPropInt( RECVINFO( m_bIsPlayerSimulated ) ),
- END_RECV_TABLE()
- #endif
- BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
- RecvPropDataTable( "AnimTimeMustBeFirst", 0, 0, &REFERENCE_RECV_TABLE(DT_AnimTimeMustBeFirst) ),
- RecvPropInt( RECVINFO(m_flSimulationTime), 0, RecvProxy_SimulationTime ),
- RecvPropInt( RECVINFO( m_ubInterpolationFrame ) ),
- RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ),
- #if PREDICTION_ERROR_CHECK_LEVEL > 1
- RecvPropVector( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
- #else
- RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
- #endif
- #ifdef DEMO_BACKWARDCOMPATABILITY
- RecvPropInt( RECVINFO(m_nModelIndex), 0, RecvProxy_IntToModelIndex16_BackCompatible ),
- #else
- RecvPropInt( RECVINFO(m_nModelIndex) ),
- #endif
- RecvPropInt(RECVINFO(m_fEffects), 0, RecvProxy_EffectFlags ),
- RecvPropInt(RECVINFO(m_nRenderMode)),
- RecvPropInt(RECVINFO(m_nRenderFX)),
- RecvPropInt(RECVINFO(m_clrRender)),
- RecvPropInt(RECVINFO(m_iTeamNum)),
- RecvPropInt(RECVINFO(m_CollisionGroup)),
- RecvPropFloat(RECVINFO(m_flElasticity)),
- RecvPropFloat(RECVINFO(m_flShadowCastDistance)),
- RecvPropEHandle( RECVINFO(m_hOwnerEntity) ),
- RecvPropEHandle( RECVINFO(m_hEffectEntity) ),
- RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
- RecvPropInt( RECVINFO( m_iParentAttachment ) ),
- RecvPropInt( "movetype", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveType ),
- RecvPropInt( "movecollide", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveCollide ),
- RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
-
- RecvPropInt( RECVINFO ( m_iTextureFrameIndex ) ),
- #if !defined( NO_ENTITY_PREDICTION )
- RecvPropDataTable( "predictable_id", 0, 0, &REFERENCE_RECV_TABLE( DT_PredictableId ) ),
- #endif
- RecvPropInt ( RECVINFO( m_bSimulatedEveryTick ), 0, RecvProxy_InterpolationAmountChanged ),
- RecvPropInt ( RECVINFO( m_bAnimatedEveryTick ), 0, RecvProxy_InterpolationAmountChanged ),
- RecvPropBool ( RECVINFO( m_bAlternateSorting ) ),
- #ifdef TF_CLIENT_DLL
- RecvPropArray3( RECVINFO_ARRAY(m_nModelIndexOverrides), RecvPropInt( RECVINFO(m_nModelIndexOverrides[0]) ) ),
- #endif
- END_RECV_TABLE()
- const float coordTolerance = 2.0f / (float)( 1 << COORD_FRACTIONAL_BITS );
- BEGIN_PREDICTION_DATA_NO_BASE( C_BaseEntity )
- // These have a special proxy to handle send/receive
- DEFINE_PRED_TYPEDESCRIPTION( m_Collision, CCollisionProperty ),
- DEFINE_PRED_FIELD( m_MoveType, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_MoveCollide, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
- DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ),
- DEFINE_PRED_FIELD_TOL( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.5f ),
- // DEFINE_PRED_FIELD( m_fEffects, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_nRenderMode, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_nRenderFX, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
- // DEFINE_PRED_FIELD( m_flAnimTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
- // DEFINE_PRED_FIELD( m_flSimulationTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_fFlags, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD_TOL( m_vecViewOffset, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.25f ),
- DEFINE_PRED_FIELD( m_nModelIndex, FIELD_SHORT, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
- DEFINE_PRED_FIELD( m_flFriction, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_iTeamNum, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
- DEFINE_PRED_FIELD( m_hOwnerEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
- // DEFINE_FIELD( m_nSimulationTick, FIELD_INTEGER ),
- DEFINE_PRED_FIELD( m_hNetworkMoveParent, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
- // DEFINE_PRED_FIELD( m_pMoveParent, FIELD_EHANDLE ),
- // DEFINE_PRED_FIELD( m_pMoveChild, FIELD_EHANDLE ),
- // DEFINE_PRED_FIELD( m_pMovePeer, FIELD_EHANDLE ),
- // DEFINE_PRED_FIELD( m_pMovePrevPeer, FIELD_EHANDLE ),
- DEFINE_PRED_FIELD_TOL( m_vecNetworkOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, coordTolerance ),
- DEFINE_PRED_FIELD( m_angNetworkAngles, FIELD_VECTOR, FTYPEDESC_INSENDTABLE | FTYPEDESC_NOERRORCHECK ),
- DEFINE_FIELD( m_vecAbsOrigin, FIELD_VECTOR ),
- DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ),
- DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ),
- DEFINE_FIELD( m_angRotation, FIELD_VECTOR ),
- // DEFINE_FIELD( m_hGroundEntity, FIELD_EHANDLE ),
- DEFINE_FIELD( m_nWaterLevel, FIELD_CHARACTER ),
- DEFINE_FIELD( m_nWaterType, FIELD_CHARACTER ),
- DEFINE_FIELD( m_vecAngVelocity, FIELD_VECTOR ),
- // DEFINE_FIELD( m_vecAbsAngVelocity, FIELD_VECTOR ),
- // DEFINE_FIELD( model, FIELD_INTEGER ), // writing pointer literally
- // DEFINE_FIELD( index, FIELD_INTEGER ),
- // DEFINE_FIELD( m_ClientHandle, FIELD_SHORT ),
- // DEFINE_FIELD( m_Partition, FIELD_SHORT ),
- // DEFINE_FIELD( m_hRender, FIELD_SHORT ),
- DEFINE_FIELD( m_bDormant, FIELD_BOOLEAN ),
- // DEFINE_FIELD( current_position, FIELD_INTEGER ),
- // DEFINE_FIELD( m_flLastMessageTime, FIELD_FLOAT ),
- DEFINE_FIELD( m_vecBaseVelocity, FIELD_VECTOR ),
- DEFINE_FIELD( m_iEFlags, FIELD_INTEGER ),
- DEFINE_FIELD( m_flGravity, FIELD_FLOAT ),
- // DEFINE_FIELD( m_ModelInstance, FIELD_SHORT ),
- DEFINE_FIELD( m_flProxyRandomValue, FIELD_FLOAT ),
- // DEFINE_FIELD( m_PredictableID, FIELD_INTEGER ),
- // DEFINE_FIELD( m_pPredictionContext, FIELD_POINTER ),
- // Stuff specific to rendering and therefore not to be copied back and forth
- // DEFINE_PRED_FIELD( m_clrRender, color32, FTYPEDESC_INSENDTABLE ),
- // DEFINE_FIELD( m_bReadyToDraw, FIELD_BOOLEAN ),
- // DEFINE_FIELD( anim, CLatchedAnim ),
- // DEFINE_FIELD( mouth, CMouthInfo ),
- // DEFINE_FIELD( GetAbsOrigin(), FIELD_VECTOR ),
- // DEFINE_FIELD( GetAbsAngles(), FIELD_VECTOR ),
- // DEFINE_FIELD( m_nNumAttachments, FIELD_SHORT ),
- // DEFINE_FIELD( m_pAttachmentAngles, FIELD_VECTOR ),
- // DEFINE_FIELD( m_pAttachmentOrigin, FIELD_VECTOR ),
- // DEFINE_FIELD( m_listentry, CSerialEntity ),
- // DEFINE_FIELD( m_ShadowHandle, ClientShadowHandle_t ),
- // DEFINE_FIELD( m_hThink, ClientThinkHandle_t ),
- // Definitely private and not copied around
- // DEFINE_FIELD( m_bPredictable, FIELD_BOOLEAN ),
- // DEFINE_FIELD( m_CollisionGroup, FIELD_INTEGER ),
- // DEFINE_FIELD( m_DataChangeEventRef, FIELD_INTEGER ),
- #if !defined( CLIENT_DLL )
- // DEFINE_FIELD( m_bPredictionEligible, FIELD_BOOLEAN ),
- #endif
- END_PREDICTION_DATA()
- //-----------------------------------------------------------------------------
- // Helper functions.
- //-----------------------------------------------------------------------------
- void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar )
- {
- Msg( "--------------------------------------------------\n" );
- int i = pVar->GetHead();
- CApparentVelocity<Vector> apparent;
- float prevtime = 0.0f;
- while ( 1 )
- {
- float changetime;
- Vector *pVal = pVar->GetHistoryValue( i, changetime );
- if ( !pVal )
- break;
- float vel = apparent.AddSample( changetime, *pVal );
- Msg( "%6.6f: (%.2f %.2f %.2f), vel: %.2f [dt %.1f]\n", changetime, VectorExpand( *pVal ), vel, prevtime == 0.0f ? 0.0f : 1000.0f * ( changetime - prevtime ) );
- i = pVar->GetNext( i );
- prevtime = changetime;
- }
- Msg( "--------------------------------------------------\n" );
- }
- void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar, float flNow, float flInterpAmount, bool bSpewAllEntries = true )
- {
- float target = flNow - flInterpAmount;
- Msg( "--------------------------------------------------\n" );
- int i = pVar->GetHead();
- CApparentVelocity<Vector> apparent;
- float newtime = 999999.0f;
- Vector newVec( 0, 0, 0 );
- bool bSpew = true;
- while ( 1 )
- {
- float changetime;
- Vector *pVal = pVar->GetHistoryValue( i, changetime );
- if ( !pVal )
- break;
- if ( bSpew && target >= changetime )
- {
- Vector o;
- pVar->DebugInterpolate( &o, flNow );
- bool bInterp = newtime != 999999.0f;
- float frac = 0.0f;
- char desc[ 32 ];
- if ( bInterp )
- {
- frac = ( target - changetime ) / ( newtime - changetime );
- Q_snprintf( desc, sizeof( desc ), "interpolated [%.2f]", frac );
- }
- else
- {
- bSpew = true;
- int savei = i;
- i = pVar->GetNext( i );
- float oldtertime = 0.0f;
- pVar->GetHistoryValue( i, oldtertime );
- if ( changetime != oldtertime )
- {
- frac = ( target - changetime ) / ( changetime - oldtertime );
- }
- Q_snprintf( desc, sizeof( desc ), "extrapolated [%.2f]", frac );
- i = savei;
- }
- if ( bSpew )
- {
- Msg( " > %6.6f: (%.2f %.2f %.2f) %s for %.1f msec\n",
- target,
- VectorExpand( o ),
- desc,
- 1000.0f * ( target - changetime ) );
- bSpew = false;
- }
- }
- float vel = apparent.AddSample( changetime, *pVal );
- if ( bSpewAllEntries )
- {
- Msg( " %6.6f: (%.2f %.2f %.2f), vel: %.2f [dt %.1f]\n", changetime, VectorExpand( *pVal ), vel, newtime == 999999.0f ? 0.0f : 1000.0f * ( newtime - changetime ) );
- }
- i = pVar->GetNext( i );
- newtime = changetime;
- newVec = *pVal;
- }
- Msg( "--------------------------------------------------\n" );
- }
- void SpewInterpolatedVar( CInterpolatedVar< float > *pVar )
- {
- Msg( "--------------------------------------------------\n" );
- int i = pVar->GetHead();
- CApparentVelocity<float> apparent;
- while ( 1 )
- {
- float changetime;
- float *pVal = pVar->GetHistoryValue( i, changetime );
- if ( !pVal )
- break;
- float vel = apparent.AddSample( changetime, *pVal );
- Msg( "%6.6f: (%.2f), vel: %.2f\n", changetime, *pVal, vel );
- i = pVar->GetNext( i );
- }
- Msg( "--------------------------------------------------\n" );
- }
- template<class T>
- void GetInterpolatedVarTimeRange( CInterpolatedVar<T> *pVar, float &flMin, float &flMax )
- {
- flMin = 1e23;
- flMax = -1e23;
- int i = pVar->GetHead();
- CApparentVelocity<Vector> apparent;
- while ( 1 )
- {
- float changetime;
- if ( !pVar->GetHistoryValue( i, changetime ) )
- return;
- flMin = MIN( flMin, changetime );
- flMax = MAX( flMax, changetime );
- i = pVar->GetNext( i );
- }
- }
- //-----------------------------------------------------------------------------
- // Global methods related to when abs data is correct
- //-----------------------------------------------------------------------------
- void C_BaseEntity::SetAbsQueriesValid( bool bValid )
- {
- // @MULTICORE: Always allow in worker threads, assume higher level code is handling correctly
- if ( !ThreadInMainThread() )
- return;
- if ( !bValid )
- {
- s_bAbsQueriesValid = false;
- }
- else
- {
- s_bAbsQueriesValid = true;
- }
- }
- bool C_BaseEntity::IsAbsQueriesValid( void )
- {
- if ( !ThreadInMainThread() )
- return true;
- return s_bAbsQueriesValid;
- }
- void C_BaseEntity::PushEnableAbsRecomputations( bool bEnable )
- {
- if ( !ThreadInMainThread() )
- return;
- if ( g_iAbsRecomputationStackPos < ARRAYSIZE( g_bAbsRecomputationStack ) )
- {
- g_bAbsRecomputationStack[g_iAbsRecomputationStackPos] = s_bAbsRecomputationEnabled;
- ++g_iAbsRecomputationStackPos;
- s_bAbsRecomputationEnabled = bEnable;
- }
- else
- {
- Assert( false );
- }
- }
- void C_BaseEntity::PopEnableAbsRecomputations()
- {
- if ( !ThreadInMainThread() )
- return;
- if ( g_iAbsRecomputationStackPos > 0 )
- {
- --g_iAbsRecomputationStackPos;
- s_bAbsRecomputationEnabled = g_bAbsRecomputationStack[g_iAbsRecomputationStackPos];
- }
- else
- {
- Assert( false );
- }
- }
- void C_BaseEntity::EnableAbsRecomputations( bool bEnable )
- {
- if ( !ThreadInMainThread() )
- return;
- // This should only be called at the frame level. Use PushEnableAbsRecomputations
- // if you're blocking out a section of code.
- Assert( g_iAbsRecomputationStackPos == 0 );
- s_bAbsRecomputationEnabled = bEnable;
- }
- bool C_BaseEntity::IsAbsRecomputationsEnabled()
- {
- if ( !ThreadInMainThread() )
- return true;
- return s_bAbsRecomputationEnabled;
- }
- int C_BaseEntity::GetTextureFrameIndex( void )
- {
- return m_iTextureFrameIndex;
- }
- void C_BaseEntity::SetTextureFrameIndex( int iIndex )
- {
- m_iTextureFrameIndex = iIndex;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : *map -
- //-----------------------------------------------------------------------------
- void C_BaseEntity::Interp_SetupMappings( VarMapping_t *map )
- {
- if( !map )
- return;
- int c = map->m_Entries.Count();
- for ( int i = 0; i < c; i++ )
- {
- VarMapEntry_t *e = &map->m_Entries[ i ];
- IInterpolatedVar *watcher = e->watcher;
- void *data = e->data;
- int type = e->type;
- watcher->Setup( data, type );
- watcher->SetInterpolationAmount( GetInterpolationAmount( watcher->GetType() ) );
- }
- }
- void C_BaseEntity::Interp_RestoreToLastNetworked( VarMapping_t *map )
- {
- VPROF( "C_BaseEntity::Interp_RestoreToLastNetworked" );
- PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( this, "restoretolastnetworked" );
- Vector oldOrigin = GetLocalOrigin();
- QAngle oldAngles = GetLocalAngles();
- Vector oldVel = GetLocalVelocity();
- int c = map->m_Entries.Count();
- for ( int i = 0; i < c; i++ )
- {
- VarMapEntry_t *e = &map->m_Entries[ i ];
- IInterpolatedVar *watcher = e->watcher;
- watcher->RestoreToLastNetworked();
- }
- BaseInterpolatePart2( oldOrigin, oldAngles, oldVel, 0 );
- }
- void C_BaseEntity::Interp_UpdateInterpolationAmounts( VarMapping_t *map )
- {
- if( !map )
- return;
- int c = map->m_Entries.Count();
- for ( int i = 0; i < c; i++ )
- {
- VarMapEntry_t *e = &map->m_Entries[ i ];
- IInterpolatedVar *watcher = e->watcher;
- watcher->SetInterpolationAmount( GetInterpolationAmount( watcher->GetType() ) );
- }
- }
- void C_BaseEntity::Interp_HierarchyUpdateInterpolationAmounts()
- {
- Interp_UpdateInterpolationAmounts( GetVarMapping() );
- for ( C_BaseEntity *pChild = FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
- {
- pChild->Interp_HierarchyUpdateInterpolationAmounts();
- }
- }
- inline int C_BaseEntity::Interp_Interpolate( VarMapping_t *map, float currentTime )
- {
- int bNoMoreChanges = 1;
- if ( currentTime < map->m_lastInterpolationTime )
- {
- for ( int i = 0; i < map->m_nInterpolatedEntries; i++ )
- {
- VarMapEntry_t *e = &map->m_Entries[ i ];
- e->m_bNeedsToInterpolate = true;
- }
- }
- map->m_lastInterpolationTime = currentTime;
- for ( int i = 0; i < map->m_nInterpolatedEntries; i++ )
- {
- VarMapEntry_t *e = &map->m_Entries[ i ];
- if ( !e->m_bNeedsToInterpolate )
- continue;
-
- IInterpolatedVar *watcher = e->watcher;
- Assert( !( watcher->GetType() & EXCLUDE_AUTO_INTERPOLATE ) );
- if ( watcher->Interpolate( currentTime ) )
- e->m_bNeedsToInterpolate = false;
- else
- bNoMoreChanges = 0;
- }
- return bNoMoreChanges;
- }
- //-----------------------------------------------------------------------------
- // Functions.
- //-----------------------------------------------------------------------------
- C_BaseEntity::C_BaseEntity() :
- m_iv_vecOrigin( "C_BaseEntity::m_iv_vecOrigin" ),
- m_iv_angRotation( "C_BaseEntity::m_iv_angRotation" ),
- m_iv_vecVelocity( "C_BaseEntity::m_iv_vecVelocity" )
- {
- AddVar( &m_vecOrigin, &m_iv_vecOrigin, LATCH_SIMULATION_VAR );
- AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR );
- // Removing this until we figure out why velocity introduces view hitching.
- // One possible fix is removing the player->ResetLatched() call in CGameMovement::FinishDuck(),
- // but that re-introduces a third-person hitching bug. One possible cause is the abrupt change
- // in player size/position that occurs when ducking, and how prediction tries to work through that.
- //
- // AddVar( &m_vecVelocity, &m_iv_vecVelocity, LATCH_SIMULATION_VAR );
- m_DataChangeEventRef = -1;
- m_EntClientFlags = 0;
- m_iParentAttachment = 0;
- m_nRenderFXBlend = 255;
- SetPredictionEligible( false );
- m_bPredictable = false;
- m_bSimulatedEveryTick = false;
- m_bAnimatedEveryTick = false;
- m_pPhysicsObject = NULL;
- #ifdef _DEBUG
- m_vecAbsOrigin = vec3_origin;
- m_angAbsRotation = vec3_angle;
- m_vecNetworkOrigin.Init();
- m_angNetworkAngles.Init();
- m_vecAbsOrigin.Init();
- // m_vecAbsAngVelocity.Init();
- m_vecVelocity.Init();
- m_vecAbsVelocity.Init();
- m_vecViewOffset.Init();
- m_vecBaseVelocity.Init();
- m_iCurrentThinkContext = NO_THINK_CONTEXT;
- #endif
- m_nSimulationTick = -1;
- // Assume drawing everything
- m_bReadyToDraw = true;
- m_flProxyRandomValue = 0.0f;
- m_fBBoxVisFlags = 0;
- #if !defined( NO_ENTITY_PREDICTION )
- m_pPredictionContext = NULL;
- #endif
-
- //NOTE: not virtual! we are in the constructor!
- C_BaseEntity::Clear();
-
- m_InterpolationListEntry = 0xFFFF;
- m_TeleportListEntry = 0xFFFF;
- #ifndef NO_TOOLFRAMEWORK
- m_bEnabledInToolView = true;
- m_bToolRecording = false;
- m_ToolHandle = 0;
- m_nLastRecordedFrame = -1;
- m_bRecordInTools = true;
- #endif
- #ifdef TF_CLIENT_DLL
- m_bValidatedOwner = false;
- m_bDeemedInvalid = false;
- m_bWasDeemedInvalid = false;
- #endif
- ParticleProp()->Init( this );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input :
- // Output :
- //-----------------------------------------------------------------------------
- C_BaseEntity::~C_BaseEntity()
- {
- Term();
- ClearDataChangedEvent( m_DataChangeEventRef );
- #if !defined( NO_ENTITY_PREDICTION )
- delete m_pPredictionContext;
- #endif
- RemoveFromInterpolationList();
- RemoveFromTeleportList();
- }
- void C_BaseEntity::Clear( void )
- {
- m_bDormant = true;
- m_nCreationTick = -1;
- m_RefEHandle.Term();
- m_ModelInstance = MODEL_INSTANCE_INVALID;
- m_ShadowHandle = CLIENTSHADOW_INVALID_HANDLE;
- m_hRender = INVALID_CLIENT_RENDER_HANDLE;
- m_hThink = INVALID_THINK_HANDLE;
- m_AimEntsListHandle = INVALID_AIMENTS_LIST_HANDLE;
- index = -1;
- m_Collision.Init( this );
- SetLocalOrigin( vec3_origin );
- SetLocalAngles( vec3_angle );
- model = NULL;
- m_vecAbsOrigin.Init();
- m_angAbsRotation.Init();
- m_vecVelocity.Init();
- ClearFlags();
- m_vecViewOffset.Init();
- m_vecBaseVelocity.Init();
- m_nModelIndex = 0;
- m_flAnimTime = 0;
- m_flSimulationTime = 0;
- SetSolid( SOLID_NONE );
- SetSolidFlags( 0 );
- SetMoveCollide( MOVECOLLIDE_DEFAULT );
- SetMoveType( MOVETYPE_NONE );
- ClearEffects();
- m_iEFlags = 0;
- m_nRenderMode = 0;
- m_nOldRenderMode = 0;
- SetRenderColor( 255, 255, 255, 255 );
- m_nRenderFX = 0;
- m_flFriction = 0.0f;
- m_flGravity = 0.0f;
- SetCheckUntouch( false );
- m_ShadowDirUseOtherEntity = NULL;
- m_nLastThinkTick = gpGlobals->tickcount;
- #if defined(SIXENSE)
- m_vecEyeOffset.Init();
- m_EyeAngleOffset.Init();
- #endif
- // Remove prediction context if it exists
- #if !defined( NO_ENTITY_PREDICTION )
- delete m_pPredictionContext;
- m_pPredictionContext = NULL;
- #endif
- // Do not enable this on all entities. It forces bone setup for entities that
- // don't need it.
- //AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
- UpdateVisibility();
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::Spawn( void )
- {
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::Activate()
- {
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::SpawnClientEntity( void )
- {
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::Precache( void )
- {
- }
- //-----------------------------------------------------------------------------
- // Purpose: Attach to entity
- // Input : *pEnt -
- // Output : Returns true on success, false on failure.
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::Init( int entnum, int iSerialNum )
- {
- Assert( entnum >= 0 && entnum < NUM_ENT_ENTRIES );
- index = entnum;
- cl_entitylist->AddNetworkableEntity( GetIClientUnknown(), entnum, iSerialNum );
- CollisionProp()->CreatePartitionHandle();
- Interp_SetupMappings( GetVarMapping() );
- m_nCreationTick = gpGlobals->tickcount;
- return true;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::InitializeAsClientEntity( const char *pszModelName, RenderGroup_t renderGroup )
- {
- int nModelIndex;
- if ( pszModelName != NULL )
- {
- nModelIndex = modelinfo->GetModelIndex( pszModelName );
-
- if ( nModelIndex == -1 )
- {
- // Model could not be found
- Assert( !"Model could not be found, index is -1" );
- return false;
- }
- }
- else
- {
- nModelIndex = -1;
- }
- Interp_SetupMappings( GetVarMapping() );
- return InitializeAsClientEntityByIndex( nModelIndex, renderGroup );
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t renderGroup )
- {
- index = -1;
- // Setup model data.
- SetModelByIndex( iIndex );
- // Add the client entity to the master entity list.
- cl_entitylist->AddNonNetworkableEntity( GetIClientUnknown() );
- Assert( GetClientHandle() != ClientEntityList().InvalidHandle() );
- // Add the client entity to the renderable "leaf system." (Renderable)
- AddToLeafSystem( renderGroup );
- // Add the client entity to the spatial partition. (Collidable)
- CollisionProp()->CreatePartitionHandle();
- SpawnClientEntity();
- return true;
- }
- void C_BaseEntity::Term()
- {
- C_BaseEntity::PhysicsRemoveTouchedList( this );
- C_BaseEntity::PhysicsRemoveGroundList( this );
- DestroyAllDataObjects();
- #if !defined( NO_ENTITY_PREDICTION )
- // Remove from the predictables list
- if ( GetPredictable() || IsClientCreated() )
- {
- g_Predictables.RemoveFromPredictablesList( GetClientHandle() );
- }
- // If it's play simulated, remove from simulation list if the player still exists...
- if ( IsPlayerSimulated() && C_BasePlayer::GetLocalPlayer() )
- {
- C_BasePlayer::GetLocalPlayer()->RemoveFromPlayerSimulationList( this );
- }
- #endif
- if ( GetClientHandle() != INVALID_CLIENTENTITY_HANDLE )
- {
- if ( GetThinkHandle() != INVALID_THINK_HANDLE )
- {
- ClientThinkList()->RemoveThinkable( GetClientHandle() );
- }
- // Remove from the client entity list.
- ClientEntityList().RemoveEntity( GetClientHandle() );
- m_RefEHandle = INVALID_CLIENTENTITY_HANDLE;
- }
-
- // Are we in the partition?
- CollisionProp()->DestroyPartitionHandle();
- // If Client side only entity index will be -1
- if ( index != -1 )
- {
- beams->KillDeadBeams( this );
- }
- // Clean up the model instance
- DestroyModelInstance();
- // Clean up drawing
- RemoveFromLeafSystem();
- RemoveFromAimEntsList();
- }
- void C_BaseEntity::SetRefEHandle( const CBaseHandle &handle )
- {
- m_RefEHandle = handle;
- }
- const CBaseHandle& C_BaseEntity::GetRefEHandle() const
- {
- return m_RefEHandle;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Free beams and destroy object
- //-----------------------------------------------------------------------------
- void C_BaseEntity::Release()
- {
- {
- C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true );
- UnlinkFromHierarchy();
- }
- // Note that this must be called from here, not the destructor, because otherwise the
- // vtable is hosed and the derived classes function is not going to get called!!!
- if ( IsIntermediateDataAllocated() )
- {
- DestroyIntermediateData();
- }
- UpdateOnRemove();
- delete this;
- }
- //-----------------------------------------------------------------------------
- // Only meant to be called from subclasses.
- // Returns true if instance valid, false otherwise
- //-----------------------------------------------------------------------------
- void C_BaseEntity::CreateModelInstance()
- {
- if ( m_ModelInstance == MODEL_INSTANCE_INVALID )
- {
- m_ModelInstance = modelrender->CreateInstance( this );
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::DestroyModelInstance()
- {
- if (m_ModelInstance != MODEL_INSTANCE_INVALID)
- {
- modelrender->DestroyInstance( m_ModelInstance );
- m_ModelInstance = MODEL_INSTANCE_INVALID;
- }
- }
- void C_BaseEntity::SetRemovalFlag( bool bRemove )
- {
- if (bRemove)
- m_iEFlags |= EFL_KILLME;
- else
- m_iEFlags &= ~EFL_KILLME;
- }
- //-----------------------------------------------------------------------------
- // VPhysics objects..
- //-----------------------------------------------------------------------------
- int C_BaseEntity::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax )
- {
- IPhysicsObject *pPhys = VPhysicsGetObject();
- if ( pPhys )
- {
- // multi-object entities must implement this function
- Assert( !(pPhys->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY) );
- if ( listMax > 0 )
- {
- pList[0] = pPhys;
- return 1;
- }
- }
- return 0;
- }
- bool C_BaseEntity::VPhysicsIsFlesh( void )
- {
- IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
- int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) );
- for ( int i = 0; i < count; i++ )
- {
- int material = pList[i]->GetMaterialIndex();
- const surfacedata_t *pSurfaceData = physprops->GetSurfaceData( material );
- // Is flesh ?, don't allow pickup
- if ( pSurfaceData->game.material == CHAR_TEX_ANTLION || pSurfaceData->game.material == CHAR_TEX_FLESH || pSurfaceData->game.material == CHAR_TEX_BLOODYFLESH || pSurfaceData->game.material == CHAR_TEX_ALIENFLESH )
- return true;
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- // Returns the health fraction
- //-----------------------------------------------------------------------------
- float C_BaseEntity::HealthFraction() const
- {
- if (GetMaxHealth() == 0)
- return 1.0f;
- float flFraction = (float)GetHealth() / (float)GetMaxHealth();
- flFraction = clamp( flFraction, 0.0f, 1.0f );
- return flFraction;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Retrieves the coordinate frame for this entity.
- // Input : forward - Receives the entity's forward vector.
- // right - Receives the entity's right vector.
- // up - Receives the entity's up vector.
- //-----------------------------------------------------------------------------
- void C_BaseEntity::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const
- {
- // This call is necessary to cause m_rgflCoordinateFrame to be recomputed
- const matrix3x4_t &entityToWorld = EntityToWorldTransform();
- if (pForward != NULL)
- {
- MatrixGetColumn( entityToWorld, 0, *pForward );
- }
- if (pRight != NULL)
- {
- MatrixGetColumn( entityToWorld, 1, *pRight );
- *pRight *= -1.0f;
- }
- if (pUp != NULL)
- {
- MatrixGetColumn( entityToWorld, 2, *pUp );
- }
- }
- void C_BaseEntity::UpdateVisibility()
- {
- #ifdef TF_CLIENT_DLL
- // TF prevents drawing of any entity attached to players that aren't items in the inventory of the player.
- // This is to prevent servers creating fake cosmetic items and attaching them to players.
- if ( !engine->IsPlayingDemo() )
- {
- static bool bIsStaging = ( engine->GetAppID() == 810 );
- if ( !m_bValidatedOwner )
- {
- bool bRetry = false;
- // Check it the first time we call update visibility (Source TV doesn't bother doing validation)
- m_bDeemedInvalid = engine->IsHLTV() ? false : !ValidateEntityAttachedToPlayer( bRetry );
- m_bValidatedOwner = !bRetry;
- }
- if ( m_bDeemedInvalid )
- {
- if ( bIsStaging )
- {
- if ( !m_bWasDeemedInvalid )
- {
- m_PreviousRenderMode = GetRenderMode();
- m_PreviousRenderColor = GetRenderColor();
- m_bWasDeemedInvalid = true;
- }
- SetRenderMode( kRenderTransColor );
- SetRenderColor( 255, 0, 0, 200 );
- }
- else
- {
- RemoveFromLeafSystem();
- return;
- }
- }
- else if ( m_bWasDeemedInvalid )
- {
- if ( bIsStaging )
- {
- // We need to fix up the rendering.
- SetRenderMode( m_PreviousRenderMode );
- SetRenderColor( m_PreviousRenderColor.r, m_PreviousRenderColor.g, m_PreviousRenderColor.b, m_PreviousRenderColor.a );
- }
- m_bWasDeemedInvalid = false;
- }
- }
- #endif
- if ( ShouldDraw() && !IsDormant() && ( !ToolsEnabled() || IsEnabledInToolView() ) )
- {
- // add/update leafsystem
- AddToLeafSystem();
- }
- else
- {
- // remove from leaf system
- RemoveFromLeafSystem();
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose: Returns whether object should render.
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::ShouldDraw()
- {
- // Only test this in tf2
- #if defined( INVASION_CLIENT_DLL )
- // Let the client mode (like commander mode) reject drawing entities.
- if (g_pClientMode && !g_pClientMode->ShouldDrawEntity(this) )
- return false;
- #endif
- // Some rendermodes prevent rendering
- if ( m_nRenderMode == kRenderNone )
- return false;
- return (model != 0) && !IsEffectActive(EF_NODRAW) && (index != 0);
- }
- bool C_BaseEntity::TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace )
- {
- return false;
- }
- bool C_BaseEntity::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr )
- {
- return false;
- }
- //-----------------------------------------------------------------------------
- // Used when the collision prop is told to ask game code for the world-space surrounding box
- //-----------------------------------------------------------------------------
- void C_BaseEntity::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
- {
- // This should only be called if you're using USE_GAME_CODE on the server
- // and you forgot to implement the client-side version of this method.
- Assert(0);
- }
- //-----------------------------------------------------------------------------
- // Purpose: Derived classes will have to write their own message cracking routines!!!
- // Input : length -
- // *data -
- //-----------------------------------------------------------------------------
- void C_BaseEntity::ReceiveMessage( int classID, bf_read &msg )
- {
- // BaseEntity doesn't have a base class we could relay this message to
- Assert( classID == GetClientClass()->m_ClassID );
-
- int messageType = msg.ReadByte();
- switch( messageType )
- {
- case BASEENTITY_MSG_REMOVE_DECALS: RemoveAllDecals();
- break;
- }
- }
- void* C_BaseEntity::GetDataTableBasePtr()
- {
- return this;
- }
- //-----------------------------------------------------------------------------
- // Should this object cast shadows?
- //-----------------------------------------------------------------------------
- ShadowType_t C_BaseEntity::ShadowCastType()
- {
- if (IsEffectActive(EF_NODRAW | EF_NOSHADOW))
- return SHADOWS_NONE;
- int modelType = modelinfo->GetModelType( model );
- return (modelType == mod_studio) ? SHADOWS_RENDER_TO_TEXTURE : SHADOWS_NONE;
- }
- //-----------------------------------------------------------------------------
- // Per-entity shadow cast distance + direction
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::GetShadowCastDistance( float *pDistance, ShadowType_t shadowType ) const
- {
- if ( m_flShadowCastDistance != 0.0f )
- {
- *pDistance = m_flShadowCastDistance;
- return true;
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- C_BaseEntity *C_BaseEntity::GetShadowUseOtherEntity( void ) const
- {
- return m_ShadowDirUseOtherEntity;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void C_BaseEntity::SetShadowUseOtherEntity( C_BaseEntity *pEntity )
- {
- m_ShadowDirUseOtherEntity = pEntity;
- }
- CInterpolatedVar< QAngle >& C_BaseEntity::GetRotationInterpolator()
- {
- return m_iv_angRotation;
- }
- CInterpolatedVar< Vector >& C_BaseEntity::GetOriginInterpolator()
- {
- return m_iv_vecOrigin;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Return a per-entity shadow cast direction
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const
- {
- if ( m_ShadowDirUseOtherEntity )
- return m_ShadowDirUseOtherEntity->GetShadowCastDirection( pDirection, shadowType );
- return false;
- }
- //-----------------------------------------------------------------------------
- // Should this object receive shadows?
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::ShouldReceiveProjectedTextures( int flags )
- {
- Assert( flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK );
- if ( IsEffectActive( EF_NODRAW ) )
- return false;
- if( flags & SHADOW_FLAGS_FLASHLIGHT )
- {
- if ( GetRenderMode() > kRenderNormal && GetRenderColor().a == 0 )
- return false;
- return true;
- }
- Assert( flags & SHADOW_FLAGS_SHADOW );
- if ( IsEffectActive( EF_NORECEIVESHADOW ) )
- return false;
- if (modelinfo->GetModelType( model ) == mod_studio)
- return false;
- return true;
- }
- //-----------------------------------------------------------------------------
- // Shadow-related methods
- //-----------------------------------------------------------------------------
- bool C_BaseEntity::IsShadowDirty( )
- {
- return IsEFlagSet( EFL_DIRTY_SHADOWUPDATE );
- }
- void C_BaseEntity::MarkShadowDirty( bool bDirty )
- {
- if ( bDirty )
- {
- AddEFlags( EFL_DIRTY_SHADOWUPDATE );
- }
- else
- {
- RemoveEFlags( EFL_DIRTY_SHADOWUPDATE );
- }
- }
- IClientRenderable *C_BaseEntity::GetShadowParent()
- {
- C_BaseEntity *pParent = GetMoveParent();
- return pParent ? pParent->GetClientRenderable() : NULL;
- }
- IClientRenderable *C_BaseEntity::FirstShadowChild()
- {
- C_BaseEntity *pChild = FirstMoveChild();
- return pChild ? pChild->GetClientRenderable() : NULL;
- }
- IClientRenderable *C_BaseEntity::NextShadowPeer()
- {
- C_BaseEntity *pPeer = NextMovePeer();
- return pPeer ? pPeer->GetClientRenderable() : NULL;
- }
-
- //-----------------------------------------------------------------------------
- // Purpose: Returns index into entities list for this entity
- // Output : Index
- //-----------------------------------------------------------------------------
- int C_BaseEntity::entindex( void ) const
- {
- return index;
- }
- int C_BaseEntity::GetSoundSourceIndex() const
- {
- #ifdef _DEBUG
- if ( index != -1 )
- {
- Assert( index == GetRefEHandle().GetEntryIndex() );
- }
- #endif
- return GetRefEHandle().GetEntryIndex();
- }
- //-----------------------------------------------------------------------------
- // Get render origin and angles
- //-----------------------------------------------------------------------------
- const Vector& C_BaseEntity::GetRenderOrigin( void )
- {
- return GetAbsOrigin();
- }
- const QAngle& C_BaseEntity::GetRenderAngles( void )
- {
- return GetAbsAngles();
- }
- const matrix3x4_t &C_BaseEntity::RenderableToWorldTransform()
- {
- return EntityToWorldTransform();
- }
- IPVSNotify* C_BaseEntity::GetPVSNotifyInterface()
- {
- return NULL;
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : theMins -
- // theMaxs -
- //-----------------------------------------------------------------------------
- void C_BaseEntity::GetRenderBounds( Vector& theMins, Vector& theMaxs )
- {
- int nModelType = modelinfo->GetModelType( model );
- if (nModelType == mod_studio || nModelType == mod_brush)
- {
- modelinfo->GetModelRenderBounds( GetModel(), theMins, theMaxs );
- }
- else
- {
- // By default, we'll just snack on the collision bounds, transform
- // them into entity-space, and call it a day.
- if ( GetRenderAngles() == CollisionProp()->GetCollisionAngles() )
- {
- theMins = CollisionProp()->OBBMins();
- theMaxs = CollisionProp()->OBBMaxs();
- }
- else
- {
- Assert( CollisionProp()->GetCollisionAngles() == vec3_angle );
- if ( IsPointSized() )
- {
- //theMins = CollisionProp()->GetCollisionOrigin();
- //theMaxs = theMins;
- theMins = theMaxs = vec3_origin;
- }
- else
- {
- // NOTE: This shouldn't happen! Or at least, I haven't run
- // into a valid case where it should yet.
- // Assert(0);
- IRotateAABB( EntityToWorldTransform(), CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), theMins, theMaxs );
- }
- }
- }
- }
- void C_BaseEntity::GetRenderBoundsWorldspace( Vector& mins, Vector& maxs )
- {
- DefaultRenderBoundsWorldspace( this, mins, maxs );
- }
- void C_BaseEntity::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType )
- {
- m_EntClientFlags |= ENTCLIENTFLAG_GETTINGSHADOWRENDERBOUNDS;
- GetRenderBounds( mins, maxs );
- m_EntClientFlags &= ~ENTCLIENTFLAG_GETTINGSHADOWRENDERBOUNDS;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Last received origin
- // Output : const float
- //-----------------------------------------------------------------------------
- const Vector& C_BaseEntity::GetAbsOrigin( void ) const
- {
- //Assert( s_bAbsQueriesValid );
- const_cast<C_BaseEntity*>(this)->CalcAbsolutePosition();
- return m_vecAbsOrigin;
- }
- //-----------------------------------------------------------------------------
- // Purpose: Last received angles
- // Output : const
- //-----------------------------------------------------------------------------
- const QAngle& C_BaseEntity::GetAbsAngles( void ) const
- {
- //Assert( s_bAbsQueriesValid );
- const_cast<C_BaseEntity*>(this…
Large files files are truncated, but you can click here to view the full file