PageRenderTime 77ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 1ms

/sp/src/game/client/c_baseentity.cpp

https://github.com/ValveSoftware/source-sdk-2013
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "c_baseentity.h"
  9. #include "prediction.h"
  10. #include "model_types.h"
  11. #include "iviewrender_beams.h"
  12. #include "dlight.h"
  13. #include "iviewrender.h"
  14. #include "view.h"
  15. #include "iefx.h"
  16. #include "c_team.h"
  17. #include "clientmode.h"
  18. #include "usercmd.h"
  19. #include "engine/IEngineSound.h"
  20. #include "engine/IEngineTrace.h"
  21. #include "engine/ivmodelinfo.h"
  22. #include "tier0/vprof.h"
  23. #include "fx_line.h"
  24. #include "interface.h"
  25. #include "materialsystem/imaterialsystem.h"
  26. #include "soundinfo.h"
  27. #include "mathlib/vmatrix.h"
  28. #include "isaverestore.h"
  29. #include "interval.h"
  30. #include "engine/ivdebugoverlay.h"
  31. #include "c_ai_basenpc.h"
  32. #include "apparent_velocity_helper.h"
  33. #include "c_baseanimatingoverlay.h"
  34. #include "tier1/KeyValues.h"
  35. #include "hltvcamera.h"
  36. #include "datacache/imdlcache.h"
  37. #include "toolframework/itoolframework.h"
  38. #include "toolframework_client.h"
  39. #include "decals.h"
  40. #include "cdll_bounded_cvars.h"
  41. #include "inetchannelinfo.h"
  42. #include "proto_version.h"
  43. // memdbgon must be the last include file in a .cpp file!!!
  44. #include "tier0/memdbgon.h"
  45. #ifdef INTERPOLATEDVAR_PARANOID_MEASUREMENT
  46. int g_nInterpolatedVarsChanged = 0;
  47. bool g_bRestoreInterpolatedVarValues = false;
  48. #endif
  49. static bool g_bWasSkipping = (bool)-1;
  50. static bool g_bWasThreaded =(bool)-1;
  51. static int g_nThreadModeTicks = 0;
  52. void cc_cl_interp_all_changed( IConVar *pConVar, const char *pOldString, float flOldValue )
  53. {
  54. ConVarRef var( pConVar );
  55. if ( var.GetInt() )
  56. {
  57. C_BaseEntityIterator iterator;
  58. C_BaseEntity *pEnt;
  59. while ( (pEnt = iterator.Next()) != NULL )
  60. {
  61. if ( pEnt->ShouldInterpolate() )
  62. {
  63. pEnt->AddToInterpolationList();
  64. }
  65. }
  66. }
  67. }
  68. static ConVar cl_extrapolate( "cl_extrapolate", "1", FCVAR_CHEAT, "Enable/disable extrapolation if interpolation history runs out." );
  69. 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)" );
  70. static ConVar cl_interp_all( "cl_interp_all", "0", 0, "Disable interpolation list optimizations.", 0, 0, 0, 0, cc_cl_interp_all_changed );
  71. ConVar r_drawmodeldecals( "r_drawmodeldecals", "1" );
  72. extern ConVar cl_showerror;
  73. int C_BaseEntity::m_nPredictionRandomSeed = -1;
  74. C_BasePlayer *C_BaseEntity::m_pPredictionPlayer = NULL;
  75. bool C_BaseEntity::s_bAbsQueriesValid = true;
  76. bool C_BaseEntity::s_bAbsRecomputationEnabled = true;
  77. bool C_BaseEntity::s_bInterpolate = true;
  78. bool C_BaseEntity::sm_bDisableTouchFuncs = false; // Disables PhysicsTouch and PhysicsStartTouch function calls
  79. static ConVar r_drawrenderboxes( "r_drawrenderboxes", "0", FCVAR_CHEAT );
  80. static bool g_bAbsRecomputationStack[8];
  81. static unsigned short g_iAbsRecomputationStackPos = 0;
  82. // All the entities that want Interpolate() called on them.
  83. static CUtlLinkedList<C_BaseEntity*, unsigned short> g_InterpolationList;
  84. static CUtlLinkedList<C_BaseEntity*, unsigned short> g_TeleportList;
  85. #if !defined( NO_ENTITY_PREDICTION )
  86. //-----------------------------------------------------------------------------
  87. // Purpose: Maintains a list of predicted or client created entities
  88. //-----------------------------------------------------------------------------
  89. class CPredictableList : public IPredictableList
  90. {
  91. public:
  92. virtual C_BaseEntity *GetPredictable( int slot );
  93. virtual int GetPredictableCount( void );
  94. protected:
  95. void AddToPredictableList( ClientEntityHandle_t add );
  96. void RemoveFromPredictablesList( ClientEntityHandle_t remove );
  97. private:
  98. CUtlVector< ClientEntityHandle_t > m_Predictables;
  99. friend class C_BaseEntity;
  100. };
  101. // Create singleton
  102. static CPredictableList g_Predictables;
  103. IPredictableList *predictables = &g_Predictables;
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Add entity to list
  106. // Input : add -
  107. // Output : int
  108. //-----------------------------------------------------------------------------
  109. void CPredictableList::AddToPredictableList( ClientEntityHandle_t add )
  110. {
  111. // This is a hack to remap slot to index
  112. if ( m_Predictables.Find( add ) != m_Predictables.InvalidIndex() )
  113. {
  114. return;
  115. }
  116. // Add to general list
  117. m_Predictables.AddToTail( add );
  118. // Maintain sort order by entindex
  119. int count = m_Predictables.Size();
  120. if ( count < 2 )
  121. return;
  122. int i, j;
  123. for ( i = 0; i < count; i++ )
  124. {
  125. for ( j = i + 1; j < count; j++ )
  126. {
  127. ClientEntityHandle_t h1 = m_Predictables[ i ];
  128. ClientEntityHandle_t h2 = m_Predictables[ j ];
  129. C_BaseEntity *p1 = cl_entitylist->GetBaseEntityFromHandle( h1 );
  130. C_BaseEntity *p2 = cl_entitylist->GetBaseEntityFromHandle( h2 );
  131. if ( !p1 || !p2 )
  132. {
  133. Assert( 0 );
  134. continue;
  135. }
  136. if ( p1->entindex() != -1 &&
  137. p2->entindex() != -1 )
  138. {
  139. if ( p1->entindex() < p2->entindex() )
  140. continue;
  141. }
  142. if ( p2->entindex() == -1 )
  143. continue;
  144. m_Predictables[ i ] = h2;
  145. m_Predictables[ j ] = h1;
  146. }
  147. }
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Purpose:
  151. // Input : remove -
  152. //-----------------------------------------------------------------------------
  153. void CPredictableList::RemoveFromPredictablesList( ClientEntityHandle_t remove )
  154. {
  155. m_Predictables.FindAndRemove( remove );
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose:
  159. // Input : slot -
  160. // Output : C_BaseEntity
  161. //-----------------------------------------------------------------------------
  162. C_BaseEntity *CPredictableList::GetPredictable( int slot )
  163. {
  164. return cl_entitylist->GetBaseEntityFromHandle( m_Predictables[ slot ] );
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose:
  168. // Output : int
  169. //-----------------------------------------------------------------------------
  170. int CPredictableList::GetPredictableCount( void )
  171. {
  172. return m_Predictables.Count();
  173. }
  174. //-----------------------------------------------------------------------------
  175. // Purpose: Searc predictables for previously created entity (by testId)
  176. // Input : testId -
  177. // Output : static C_BaseEntity
  178. //-----------------------------------------------------------------------------
  179. static C_BaseEntity *FindPreviouslyCreatedEntity( CPredictableId& testId )
  180. {
  181. int c = predictables->GetPredictableCount();
  182. int i;
  183. for ( i = 0; i < c; i++ )
  184. {
  185. C_BaseEntity *e = predictables->GetPredictable( i );
  186. if ( !e || !e->IsClientCreated() )
  187. continue;
  188. // Found it, note use of operator ==
  189. if ( testId == e->m_PredictableID )
  190. {
  191. return e;
  192. }
  193. }
  194. return NULL;
  195. }
  196. #endif
  197. abstract_class IRecordingList
  198. {
  199. public:
  200. virtual ~IRecordingList() {};
  201. virtual void AddToList( ClientEntityHandle_t add ) = 0;
  202. virtual void RemoveFromList( ClientEntityHandle_t remove ) = 0;
  203. virtual int Count() = 0;
  204. virtual IClientRenderable *Get( int index ) = 0;
  205. };
  206. class CRecordingList : public IRecordingList
  207. {
  208. public:
  209. virtual void AddToList( ClientEntityHandle_t add );
  210. virtual void RemoveFromList( ClientEntityHandle_t remove );
  211. virtual int Count();
  212. IClientRenderable *Get( int index );
  213. private:
  214. CUtlVector< ClientEntityHandle_t > m_Recording;
  215. };
  216. static CRecordingList g_RecordingList;
  217. IRecordingList *recordinglist = &g_RecordingList;
  218. //-----------------------------------------------------------------------------
  219. // Purpose: Add entity to list
  220. // Input : add -
  221. // Output : int
  222. //-----------------------------------------------------------------------------
  223. void CRecordingList::AddToList( ClientEntityHandle_t add )
  224. {
  225. // This is a hack to remap slot to index
  226. if ( m_Recording.Find( add ) != m_Recording.InvalidIndex() )
  227. {
  228. return;
  229. }
  230. // Add to general list
  231. m_Recording.AddToTail( add );
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose:
  235. // Input : remove -
  236. //-----------------------------------------------------------------------------
  237. void CRecordingList::RemoveFromList( ClientEntityHandle_t remove )
  238. {
  239. m_Recording.FindAndRemove( remove );
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Purpose:
  243. // Input : slot -
  244. // Output : IClientRenderable
  245. //-----------------------------------------------------------------------------
  246. IClientRenderable *CRecordingList::Get( int index )
  247. {
  248. return cl_entitylist->GetClientRenderableFromHandle( m_Recording[ index ] );
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose:
  252. // Output : int
  253. //-----------------------------------------------------------------------------
  254. int CRecordingList::Count()
  255. {
  256. return m_Recording.Count();
  257. }
  258. // Should these be somewhere else?
  259. #define PITCH 0
  260. //-----------------------------------------------------------------------------
  261. // Purpose: Decodes animtime and notes when it changes
  262. // Input : *pStruct - ( C_BaseEntity * ) used to flag animtime is changine
  263. // *pVarData -
  264. // *pIn -
  265. // objectID -
  266. //-----------------------------------------------------------------------------
  267. void RecvProxy_AnimTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
  268. {
  269. C_BaseEntity *pEntity = ( C_BaseEntity * )pStruct;
  270. Assert( pOut == &pEntity->m_flAnimTime );
  271. int t;
  272. int tickbase;
  273. int addt;
  274. // Unpack the data.
  275. addt = pData->m_Value.m_Int;
  276. // Note, this needs to be encoded relative to packet timestamp, not raw client clock
  277. tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() );
  278. t = tickbase;
  279. // and then go back to floating point time.
  280. t += addt; // Add in an additional up to 256 100ths from the server
  281. // center m_flAnimTime around current time.
  282. while (t < gpGlobals->tickcount - 127)
  283. t += 256;
  284. while (t > gpGlobals->tickcount + 127)
  285. t -= 256;
  286. pEntity->m_flAnimTime = ( t * TICK_INTERVAL );
  287. }
  288. void RecvProxy_SimulationTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
  289. {
  290. C_BaseEntity *pEntity = ( C_BaseEntity * )pStruct;
  291. Assert( pOut == &pEntity->m_flSimulationTime );
  292. int t;
  293. int tickbase;
  294. int addt;
  295. // Unpack the data.
  296. addt = pData->m_Value.m_Int;
  297. // Note, this needs to be encoded relative to packet timestamp, not raw client clock
  298. tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() );
  299. t = tickbase;
  300. // and then go back to floating point time.
  301. t += addt; // Add in an additional up to 256 100ths from the server
  302. // center m_flSimulationTime around current time.
  303. while (t < gpGlobals->tickcount - 127)
  304. t += 256;
  305. while (t > gpGlobals->tickcount + 127)
  306. t -= 256;
  307. pEntity->m_flSimulationTime = ( t * TICK_INTERVAL );
  308. }
  309. void RecvProxy_LocalVelocity( const CRecvProxyData *pData, void *pStruct, void *pOut )
  310. {
  311. CBaseEntity *pEnt = (CBaseEntity *)pStruct;
  312. Vector vecVelocity;
  313. vecVelocity.x = pData->m_Value.m_Vector[0];
  314. vecVelocity.y = pData->m_Value.m_Vector[1];
  315. vecVelocity.z = pData->m_Value.m_Vector[2];
  316. // SetLocalVelocity checks to see if the value has changed
  317. pEnt->SetLocalVelocity( vecVelocity );
  318. }
  319. void RecvProxy_ToolRecording( const CRecvProxyData *pData, void *pStruct, void *pOut )
  320. {
  321. if ( !ToolsEnabled() )
  322. return;
  323. CBaseEntity *pEnt = (CBaseEntity *)pStruct;
  324. pEnt->SetToolRecording( pData->m_Value.m_Int != 0 );
  325. }
  326. // Expose it to the engine.
  327. IMPLEMENT_CLIENTCLASS(C_BaseEntity, DT_BaseEntity, CBaseEntity);
  328. static void RecvProxy_MoveType( const CRecvProxyData *pData, void *pStruct, void *pOut )
  329. {
  330. ((C_BaseEntity*)pStruct)->SetMoveType( (MoveType_t)(pData->m_Value.m_Int) );
  331. }
  332. static void RecvProxy_MoveCollide( const CRecvProxyData *pData, void *pStruct, void *pOut )
  333. {
  334. ((C_BaseEntity*)pStruct)->SetMoveCollide( (MoveCollide_t)(pData->m_Value.m_Int) );
  335. }
  336. static void RecvProxy_Solid( const CRecvProxyData *pData, void *pStruct, void *pOut )
  337. {
  338. ((C_BaseEntity*)pStruct)->SetSolid( (SolidType_t)pData->m_Value.m_Int );
  339. }
  340. static void RecvProxy_SolidFlags( const CRecvProxyData *pData, void *pStruct, void *pOut )
  341. {
  342. ((C_BaseEntity*)pStruct)->SetSolidFlags( pData->m_Value.m_Int );
  343. }
  344. void RecvProxy_EffectFlags( const CRecvProxyData *pData, void *pStruct, void *pOut )
  345. {
  346. ((C_BaseEntity*)pStruct)->SetEffects( pData->m_Value.m_Int );
  347. }
  348. BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
  349. RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
  350. END_RECV_TABLE()
  351. #ifndef NO_ENTITY_PREDICTION
  352. BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_PredictableId )
  353. RecvPropPredictableId( RECVINFO( m_PredictableID ) ),
  354. RecvPropInt( RECVINFO( m_bIsPlayerSimulated ) ),
  355. END_RECV_TABLE()
  356. #endif
  357. BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
  358. RecvPropDataTable( "AnimTimeMustBeFirst", 0, 0, &REFERENCE_RECV_TABLE(DT_AnimTimeMustBeFirst) ),
  359. RecvPropInt( RECVINFO(m_flSimulationTime), 0, RecvProxy_SimulationTime ),
  360. RecvPropInt( RECVINFO( m_ubInterpolationFrame ) ),
  361. RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ),
  362. #if PREDICTION_ERROR_CHECK_LEVEL > 1
  363. RecvPropVector( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
  364. #else
  365. RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
  366. #endif
  367. #ifdef DEMO_BACKWARDCOMPATABILITY
  368. RecvPropInt( RECVINFO(m_nModelIndex), 0, RecvProxy_IntToModelIndex16_BackCompatible ),
  369. #else
  370. RecvPropInt( RECVINFO(m_nModelIndex) ),
  371. #endif
  372. RecvPropInt(RECVINFO(m_fEffects), 0, RecvProxy_EffectFlags ),
  373. RecvPropInt(RECVINFO(m_nRenderMode)),
  374. RecvPropInt(RECVINFO(m_nRenderFX)),
  375. RecvPropInt(RECVINFO(m_clrRender)),
  376. RecvPropInt(RECVINFO(m_iTeamNum)),
  377. RecvPropInt(RECVINFO(m_CollisionGroup)),
  378. RecvPropFloat(RECVINFO(m_flElasticity)),
  379. RecvPropFloat(RECVINFO(m_flShadowCastDistance)),
  380. RecvPropEHandle( RECVINFO(m_hOwnerEntity) ),
  381. RecvPropEHandle( RECVINFO(m_hEffectEntity) ),
  382. RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
  383. RecvPropInt( RECVINFO( m_iParentAttachment ) ),
  384. RecvPropInt( "movetype", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveType ),
  385. RecvPropInt( "movecollide", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveCollide ),
  386. RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
  387. RecvPropInt( RECVINFO ( m_iTextureFrameIndex ) ),
  388. #if !defined( NO_ENTITY_PREDICTION )
  389. RecvPropDataTable( "predictable_id", 0, 0, &REFERENCE_RECV_TABLE( DT_PredictableId ) ),
  390. #endif
  391. RecvPropInt ( RECVINFO( m_bSimulatedEveryTick ), 0, RecvProxy_InterpolationAmountChanged ),
  392. RecvPropInt ( RECVINFO( m_bAnimatedEveryTick ), 0, RecvProxy_InterpolationAmountChanged ),
  393. RecvPropBool ( RECVINFO( m_bAlternateSorting ) ),
  394. #ifdef TF_CLIENT_DLL
  395. RecvPropArray3( RECVINFO_ARRAY(m_nModelIndexOverrides), RecvPropInt( RECVINFO(m_nModelIndexOverrides[0]) ) ),
  396. #endif
  397. END_RECV_TABLE()
  398. const float coordTolerance = 2.0f / (float)( 1 << COORD_FRACTIONAL_BITS );
  399. BEGIN_PREDICTION_DATA_NO_BASE( C_BaseEntity )
  400. // These have a special proxy to handle send/receive
  401. DEFINE_PRED_TYPEDESCRIPTION( m_Collision, CCollisionProperty ),
  402. DEFINE_PRED_FIELD( m_MoveType, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
  403. DEFINE_PRED_FIELD( m_MoveCollide, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
  404. DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ),
  405. DEFINE_PRED_FIELD_TOL( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.5f ),
  406. // DEFINE_PRED_FIELD( m_fEffects, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  407. DEFINE_PRED_FIELD( m_nRenderMode, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
  408. DEFINE_PRED_FIELD( m_nRenderFX, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ),
  409. // DEFINE_PRED_FIELD( m_flAnimTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  410. // DEFINE_PRED_FIELD( m_flSimulationTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  411. DEFINE_PRED_FIELD( m_fFlags, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  412. DEFINE_PRED_FIELD_TOL( m_vecViewOffset, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.25f ),
  413. DEFINE_PRED_FIELD( m_nModelIndex, FIELD_SHORT, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
  414. DEFINE_PRED_FIELD( m_flFriction, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  415. DEFINE_PRED_FIELD( m_iTeamNum, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  416. DEFINE_PRED_FIELD( m_hOwnerEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
  417. // DEFINE_FIELD( m_nSimulationTick, FIELD_INTEGER ),
  418. DEFINE_PRED_FIELD( m_hNetworkMoveParent, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
  419. // DEFINE_PRED_FIELD( m_pMoveParent, FIELD_EHANDLE ),
  420. // DEFINE_PRED_FIELD( m_pMoveChild, FIELD_EHANDLE ),
  421. // DEFINE_PRED_FIELD( m_pMovePeer, FIELD_EHANDLE ),
  422. // DEFINE_PRED_FIELD( m_pMovePrevPeer, FIELD_EHANDLE ),
  423. DEFINE_PRED_FIELD_TOL( m_vecNetworkOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, coordTolerance ),
  424. DEFINE_PRED_FIELD( m_angNetworkAngles, FIELD_VECTOR, FTYPEDESC_INSENDTABLE | FTYPEDESC_NOERRORCHECK ),
  425. DEFINE_FIELD( m_vecAbsOrigin, FIELD_VECTOR ),
  426. DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ),
  427. DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ),
  428. DEFINE_FIELD( m_angRotation, FIELD_VECTOR ),
  429. // DEFINE_FIELD( m_hGroundEntity, FIELD_EHANDLE ),
  430. DEFINE_FIELD( m_nWaterLevel, FIELD_CHARACTER ),
  431. DEFINE_FIELD( m_nWaterType, FIELD_CHARACTER ),
  432. DEFINE_FIELD( m_vecAngVelocity, FIELD_VECTOR ),
  433. // DEFINE_FIELD( m_vecAbsAngVelocity, FIELD_VECTOR ),
  434. // DEFINE_FIELD( model, FIELD_INTEGER ), // writing pointer literally
  435. // DEFINE_FIELD( index, FIELD_INTEGER ),
  436. // DEFINE_FIELD( m_ClientHandle, FIELD_SHORT ),
  437. // DEFINE_FIELD( m_Partition, FIELD_SHORT ),
  438. // DEFINE_FIELD( m_hRender, FIELD_SHORT ),
  439. DEFINE_FIELD( m_bDormant, FIELD_BOOLEAN ),
  440. // DEFINE_FIELD( current_position, FIELD_INTEGER ),
  441. // DEFINE_FIELD( m_flLastMessageTime, FIELD_FLOAT ),
  442. DEFINE_FIELD( m_vecBaseVelocity, FIELD_VECTOR ),
  443. DEFINE_FIELD( m_iEFlags, FIELD_INTEGER ),
  444. DEFINE_FIELD( m_flGravity, FIELD_FLOAT ),
  445. // DEFINE_FIELD( m_ModelInstance, FIELD_SHORT ),
  446. DEFINE_FIELD( m_flProxyRandomValue, FIELD_FLOAT ),
  447. // DEFINE_FIELD( m_PredictableID, FIELD_INTEGER ),
  448. // DEFINE_FIELD( m_pPredictionContext, FIELD_POINTER ),
  449. // Stuff specific to rendering and therefore not to be copied back and forth
  450. // DEFINE_PRED_FIELD( m_clrRender, color32, FTYPEDESC_INSENDTABLE ),
  451. // DEFINE_FIELD( m_bReadyToDraw, FIELD_BOOLEAN ),
  452. // DEFINE_FIELD( anim, CLatchedAnim ),
  453. // DEFINE_FIELD( mouth, CMouthInfo ),
  454. // DEFINE_FIELD( GetAbsOrigin(), FIELD_VECTOR ),
  455. // DEFINE_FIELD( GetAbsAngles(), FIELD_VECTOR ),
  456. // DEFINE_FIELD( m_nNumAttachments, FIELD_SHORT ),
  457. // DEFINE_FIELD( m_pAttachmentAngles, FIELD_VECTOR ),
  458. // DEFINE_FIELD( m_pAttachmentOrigin, FIELD_VECTOR ),
  459. // DEFINE_FIELD( m_listentry, CSerialEntity ),
  460. // DEFINE_FIELD( m_ShadowHandle, ClientShadowHandle_t ),
  461. // DEFINE_FIELD( m_hThink, ClientThinkHandle_t ),
  462. // Definitely private and not copied around
  463. // DEFINE_FIELD( m_bPredictable, FIELD_BOOLEAN ),
  464. // DEFINE_FIELD( m_CollisionGroup, FIELD_INTEGER ),
  465. // DEFINE_FIELD( m_DataChangeEventRef, FIELD_INTEGER ),
  466. #if !defined( CLIENT_DLL )
  467. // DEFINE_FIELD( m_bPredictionEligible, FIELD_BOOLEAN ),
  468. #endif
  469. END_PREDICTION_DATA()
  470. //-----------------------------------------------------------------------------
  471. // Helper functions.
  472. //-----------------------------------------------------------------------------
  473. void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar )
  474. {
  475. Msg( "--------------------------------------------------\n" );
  476. int i = pVar->GetHead();
  477. CApparentVelocity<Vector> apparent;
  478. float prevtime = 0.0f;
  479. while ( 1 )
  480. {
  481. float changetime;
  482. Vector *pVal = pVar->GetHistoryValue( i, changetime );
  483. if ( !pVal )
  484. break;
  485. float vel = apparent.AddSample( changetime, *pVal );
  486. Msg( "%6.6f: (%.2f %.2f %.2f), vel: %.2f [dt %.1f]\n", changetime, VectorExpand( *pVal ), vel, prevtime == 0.0f ? 0.0f : 1000.0f * ( changetime - prevtime ) );
  487. i = pVar->GetNext( i );
  488. prevtime = changetime;
  489. }
  490. Msg( "--------------------------------------------------\n" );
  491. }
  492. void SpewInterpolatedVar( CInterpolatedVar< Vector > *pVar, float flNow, float flInterpAmount, bool bSpewAllEntries = true )
  493. {
  494. float target = flNow - flInterpAmount;
  495. Msg( "--------------------------------------------------\n" );
  496. int i = pVar->GetHead();
  497. CApparentVelocity<Vector> apparent;
  498. float newtime = 999999.0f;
  499. Vector newVec( 0, 0, 0 );
  500. bool bSpew = true;
  501. while ( 1 )
  502. {
  503. float changetime;
  504. Vector *pVal = pVar->GetHistoryValue( i, changetime );
  505. if ( !pVal )
  506. break;
  507. if ( bSpew && target >= changetime )
  508. {
  509. Vector o;
  510. pVar->DebugInterpolate( &o, flNow );
  511. bool bInterp = newtime != 999999.0f;
  512. float frac = 0.0f;
  513. char desc[ 32 ];
  514. if ( bInterp )
  515. {
  516. frac = ( target - changetime ) / ( newtime - changetime );
  517. Q_snprintf( desc, sizeof( desc ), "interpolated [%.2f]", frac );
  518. }
  519. else
  520. {
  521. bSpew = true;
  522. int savei = i;
  523. i = pVar->GetNext( i );
  524. float oldtertime = 0.0f;
  525. pVar->GetHistoryValue( i, oldtertime );
  526. if ( changetime != oldtertime )
  527. {
  528. frac = ( target - changetime ) / ( changetime - oldtertime );
  529. }
  530. Q_snprintf( desc, sizeof( desc ), "extrapolated [%.2f]", frac );
  531. i = savei;
  532. }
  533. if ( bSpew )
  534. {
  535. Msg( " > %6.6f: (%.2f %.2f %.2f) %s for %.1f msec\n",
  536. target,
  537. VectorExpand( o ),
  538. desc,
  539. 1000.0f * ( target - changetime ) );
  540. bSpew = false;
  541. }
  542. }
  543. float vel = apparent.AddSample( changetime, *pVal );
  544. if ( bSpewAllEntries )
  545. {
  546. Msg( " %6.6f: (%.2f %.2f %.2f), vel: %.2f [dt %.1f]\n", changetime, VectorExpand( *pVal ), vel, newtime == 999999.0f ? 0.0f : 1000.0f * ( newtime - changetime ) );
  547. }
  548. i = pVar->GetNext( i );
  549. newtime = changetime;
  550. newVec = *pVal;
  551. }
  552. Msg( "--------------------------------------------------\n" );
  553. }
  554. void SpewInterpolatedVar( CInterpolatedVar< float > *pVar )
  555. {
  556. Msg( "--------------------------------------------------\n" );
  557. int i = pVar->GetHead();
  558. CApparentVelocity<float> apparent;
  559. while ( 1 )
  560. {
  561. float changetime;
  562. float *pVal = pVar->GetHistoryValue( i, changetime );
  563. if ( !pVal )
  564. break;
  565. float vel = apparent.AddSample( changetime, *pVal );
  566. Msg( "%6.6f: (%.2f), vel: %.2f\n", changetime, *pVal, vel );
  567. i = pVar->GetNext( i );
  568. }
  569. Msg( "--------------------------------------------------\n" );
  570. }
  571. template<class T>
  572. void GetInterpolatedVarTimeRange( CInterpolatedVar<T> *pVar, float &flMin, float &flMax )
  573. {
  574. flMin = 1e23;
  575. flMax = -1e23;
  576. int i = pVar->GetHead();
  577. CApparentVelocity<Vector> apparent;
  578. while ( 1 )
  579. {
  580. float changetime;
  581. if ( !pVar->GetHistoryValue( i, changetime ) )
  582. return;
  583. flMin = MIN( flMin, changetime );
  584. flMax = MAX( flMax, changetime );
  585. i = pVar->GetNext( i );
  586. }
  587. }
  588. //-----------------------------------------------------------------------------
  589. // Global methods related to when abs data is correct
  590. //-----------------------------------------------------------------------------
  591. void C_BaseEntity::SetAbsQueriesValid( bool bValid )
  592. {
  593. // @MULTICORE: Always allow in worker threads, assume higher level code is handling correctly
  594. if ( !ThreadInMainThread() )
  595. return;
  596. if ( !bValid )
  597. {
  598. s_bAbsQueriesValid = false;
  599. }
  600. else
  601. {
  602. s_bAbsQueriesValid = true;
  603. }
  604. }
  605. bool C_BaseEntity::IsAbsQueriesValid( void )
  606. {
  607. if ( !ThreadInMainThread() )
  608. return true;
  609. return s_bAbsQueriesValid;
  610. }
  611. void C_BaseEntity::PushEnableAbsRecomputations( bool bEnable )
  612. {
  613. if ( !ThreadInMainThread() )
  614. return;
  615. if ( g_iAbsRecomputationStackPos < ARRAYSIZE( g_bAbsRecomputationStack ) )
  616. {
  617. g_bAbsRecomputationStack[g_iAbsRecomputationStackPos] = s_bAbsRecomputationEnabled;
  618. ++g_iAbsRecomputationStackPos;
  619. s_bAbsRecomputationEnabled = bEnable;
  620. }
  621. else
  622. {
  623. Assert( false );
  624. }
  625. }
  626. void C_BaseEntity::PopEnableAbsRecomputations()
  627. {
  628. if ( !ThreadInMainThread() )
  629. return;
  630. if ( g_iAbsRecomputationStackPos > 0 )
  631. {
  632. --g_iAbsRecomputationStackPos;
  633. s_bAbsRecomputationEnabled = g_bAbsRecomputationStack[g_iAbsRecomputationStackPos];
  634. }
  635. else
  636. {
  637. Assert( false );
  638. }
  639. }
  640. void C_BaseEntity::EnableAbsRecomputations( bool bEnable )
  641. {
  642. if ( !ThreadInMainThread() )
  643. return;
  644. // This should only be called at the frame level. Use PushEnableAbsRecomputations
  645. // if you're blocking out a section of code.
  646. Assert( g_iAbsRecomputationStackPos == 0 );
  647. s_bAbsRecomputationEnabled = bEnable;
  648. }
  649. bool C_BaseEntity::IsAbsRecomputationsEnabled()
  650. {
  651. if ( !ThreadInMainThread() )
  652. return true;
  653. return s_bAbsRecomputationEnabled;
  654. }
  655. int C_BaseEntity::GetTextureFrameIndex( void )
  656. {
  657. return m_iTextureFrameIndex;
  658. }
  659. void C_BaseEntity::SetTextureFrameIndex( int iIndex )
  660. {
  661. m_iTextureFrameIndex = iIndex;
  662. }
  663. //-----------------------------------------------------------------------------
  664. // Purpose:
  665. // Input : *map -
  666. //-----------------------------------------------------------------------------
  667. void C_BaseEntity::Interp_SetupMappings( VarMapping_t *map )
  668. {
  669. if( !map )
  670. return;
  671. int c = map->m_Entries.Count();
  672. for ( int i = 0; i < c; i++ )
  673. {
  674. VarMapEntry_t *e = &map->m_Entries[ i ];
  675. IInterpolatedVar *watcher = e->watcher;
  676. void *data = e->data;
  677. int type = e->type;
  678. watcher->Setup( data, type );
  679. watcher->SetInterpolationAmount( GetInterpolationAmount( watcher->GetType() ) );
  680. }
  681. }
  682. void C_BaseEntity::Interp_RestoreToLastNetworked( VarMapping_t *map )
  683. {
  684. VPROF( "C_BaseEntity::Interp_RestoreToLastNetworked" );
  685. PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( this, "restoretolastnetworked" );
  686. Vector oldOrigin = GetLocalOrigin();
  687. QAngle oldAngles = GetLocalAngles();
  688. Vector oldVel = GetLocalVelocity();
  689. int c = map->m_Entries.Count();
  690. for ( int i = 0; i < c; i++ )
  691. {
  692. VarMapEntry_t *e = &map->m_Entries[ i ];
  693. IInterpolatedVar *watcher = e->watcher;
  694. watcher->RestoreToLastNetworked();
  695. }
  696. BaseInterpolatePart2( oldOrigin, oldAngles, oldVel, 0 );
  697. }
  698. void C_BaseEntity::Interp_UpdateInterpolationAmounts( VarMapping_t *map )
  699. {
  700. if( !map )
  701. return;
  702. int c = map->m_Entries.Count();
  703. for ( int i = 0; i < c; i++ )
  704. {
  705. VarMapEntry_t *e = &map->m_Entries[ i ];
  706. IInterpolatedVar *watcher = e->watcher;
  707. watcher->SetInterpolationAmount( GetInterpolationAmount( watcher->GetType() ) );
  708. }
  709. }
  710. void C_BaseEntity::Interp_HierarchyUpdateInterpolationAmounts()
  711. {
  712. Interp_UpdateInterpolationAmounts( GetVarMapping() );
  713. for ( C_BaseEntity *pChild = FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
  714. {
  715. pChild->Interp_HierarchyUpdateInterpolationAmounts();
  716. }
  717. }
  718. inline int C_BaseEntity::Interp_Interpolate( VarMapping_t *map, float currentTime )
  719. {
  720. int bNoMoreChanges = 1;
  721. if ( currentTime < map->m_lastInterpolationTime )
  722. {
  723. for ( int i = 0; i < map->m_nInterpolatedEntries; i++ )
  724. {
  725. VarMapEntry_t *e = &map->m_Entries[ i ];
  726. e->m_bNeedsToInterpolate = true;
  727. }
  728. }
  729. map->m_lastInterpolationTime = currentTime;
  730. for ( int i = 0; i < map->m_nInterpolatedEntries; i++ )
  731. {
  732. VarMapEntry_t *e = &map->m_Entries[ i ];
  733. if ( !e->m_bNeedsToInterpolate )
  734. continue;
  735. IInterpolatedVar *watcher = e->watcher;
  736. Assert( !( watcher->GetType() & EXCLUDE_AUTO_INTERPOLATE ) );
  737. if ( watcher->Interpolate( currentTime ) )
  738. e->m_bNeedsToInterpolate = false;
  739. else
  740. bNoMoreChanges = 0;
  741. }
  742. return bNoMoreChanges;
  743. }
  744. //-----------------------------------------------------------------------------
  745. // Functions.
  746. //-----------------------------------------------------------------------------
  747. C_BaseEntity::C_BaseEntity() :
  748. m_iv_vecOrigin( "C_BaseEntity::m_iv_vecOrigin" ),
  749. m_iv_angRotation( "C_BaseEntity::m_iv_angRotation" ),
  750. m_iv_vecVelocity( "C_BaseEntity::m_iv_vecVelocity" )
  751. {
  752. AddVar( &m_vecOrigin, &m_iv_vecOrigin, LATCH_SIMULATION_VAR );
  753. AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR );
  754. // Removing this until we figure out why velocity introduces view hitching.
  755. // One possible fix is removing the player->ResetLatched() call in CGameMovement::FinishDuck(),
  756. // but that re-introduces a third-person hitching bug. One possible cause is the abrupt change
  757. // in player size/position that occurs when ducking, and how prediction tries to work through that.
  758. //
  759. // AddVar( &m_vecVelocity, &m_iv_vecVelocity, LATCH_SIMULATION_VAR );
  760. m_DataChangeEventRef = -1;
  761. m_EntClientFlags = 0;
  762. m_iParentAttachment = 0;
  763. m_nRenderFXBlend = 255;
  764. SetPredictionEligible( false );
  765. m_bPredictable = false;
  766. m_bSimulatedEveryTick = false;
  767. m_bAnimatedEveryTick = false;
  768. m_pPhysicsObject = NULL;
  769. #ifdef _DEBUG
  770. m_vecAbsOrigin = vec3_origin;
  771. m_angAbsRotation = vec3_angle;
  772. m_vecNetworkOrigin.Init();
  773. m_angNetworkAngles.Init();
  774. m_vecAbsOrigin.Init();
  775. // m_vecAbsAngVelocity.Init();
  776. m_vecVelocity.Init();
  777. m_vecAbsVelocity.Init();
  778. m_vecViewOffset.Init();
  779. m_vecBaseVelocity.Init();
  780. m_iCurrentThinkContext = NO_THINK_CONTEXT;
  781. #endif
  782. m_nSimulationTick = -1;
  783. // Assume drawing everything
  784. m_bReadyToDraw = true;
  785. m_flProxyRandomValue = 0.0f;
  786. m_fBBoxVisFlags = 0;
  787. #if !defined( NO_ENTITY_PREDICTION )
  788. m_pPredictionContext = NULL;
  789. #endif
  790. //NOTE: not virtual! we are in the constructor!
  791. C_BaseEntity::Clear();
  792. m_InterpolationListEntry = 0xFFFF;
  793. m_TeleportListEntry = 0xFFFF;
  794. #ifndef NO_TOOLFRAMEWORK
  795. m_bEnabledInToolView = true;
  796. m_bToolRecording = false;
  797. m_ToolHandle = 0;
  798. m_nLastRecordedFrame = -1;
  799. m_bRecordInTools = true;
  800. #endif
  801. #ifdef TF_CLIENT_DLL
  802. m_bValidatedOwner = false;
  803. m_bDeemedInvalid = false;
  804. m_bWasDeemedInvalid = false;
  805. #endif
  806. ParticleProp()->Init( this );
  807. }
  808. //-----------------------------------------------------------------------------
  809. // Purpose:
  810. // Input :
  811. // Output :
  812. //-----------------------------------------------------------------------------
  813. C_BaseEntity::~C_BaseEntity()
  814. {
  815. Term();
  816. ClearDataChangedEvent( m_DataChangeEventRef );
  817. #if !defined( NO_ENTITY_PREDICTION )
  818. delete m_pPredictionContext;
  819. #endif
  820. RemoveFromInterpolationList();
  821. RemoveFromTeleportList();
  822. }
  823. void C_BaseEntity::Clear( void )
  824. {
  825. m_bDormant = true;
  826. m_nCreationTick = -1;
  827. m_RefEHandle.Term();
  828. m_ModelInstance = MODEL_INSTANCE_INVALID;
  829. m_ShadowHandle = CLIENTSHADOW_INVALID_HANDLE;
  830. m_hRender = INVALID_CLIENT_RENDER_HANDLE;
  831. m_hThink = INVALID_THINK_HANDLE;
  832. m_AimEntsListHandle = INVALID_AIMENTS_LIST_HANDLE;
  833. index = -1;
  834. m_Collision.Init( this );
  835. SetLocalOrigin( vec3_origin );
  836. SetLocalAngles( vec3_angle );
  837. model = NULL;
  838. m_vecAbsOrigin.Init();
  839. m_angAbsRotation.Init();
  840. m_vecVelocity.Init();
  841. ClearFlags();
  842. m_vecViewOffset.Init();
  843. m_vecBaseVelocity.Init();
  844. m_nModelIndex = 0;
  845. m_flAnimTime = 0;
  846. m_flSimulationTime = 0;
  847. SetSolid( SOLID_NONE );
  848. SetSolidFlags( 0 );
  849. SetMoveCollide( MOVECOLLIDE_DEFAULT );
  850. SetMoveType( MOVETYPE_NONE );
  851. ClearEffects();
  852. m_iEFlags = 0;
  853. m_nRenderMode = 0;
  854. m_nOldRenderMode = 0;
  855. SetRenderColor( 255, 255, 255, 255 );
  856. m_nRenderFX = 0;
  857. m_flFriction = 0.0f;
  858. m_flGravity = 0.0f;
  859. SetCheckUntouch( false );
  860. m_ShadowDirUseOtherEntity = NULL;
  861. m_nLastThinkTick = gpGlobals->tickcount;
  862. #if defined(SIXENSE)
  863. m_vecEyeOffset.Init();
  864. m_EyeAngleOffset.Init();
  865. #endif
  866. // Remove prediction context if it exists
  867. #if !defined( NO_ENTITY_PREDICTION )
  868. delete m_pPredictionContext;
  869. m_pPredictionContext = NULL;
  870. #endif
  871. // Do not enable this on all entities. It forces bone setup for entities that
  872. // don't need it.
  873. //AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
  874. UpdateVisibility();
  875. }
  876. //-----------------------------------------------------------------------------
  877. // Purpose:
  878. //-----------------------------------------------------------------------------
  879. void C_BaseEntity::Spawn( void )
  880. {
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Purpose:
  884. //-----------------------------------------------------------------------------
  885. void C_BaseEntity::Activate()
  886. {
  887. }
  888. //-----------------------------------------------------------------------------
  889. // Purpose:
  890. //-----------------------------------------------------------------------------
  891. void C_BaseEntity::SpawnClientEntity( void )
  892. {
  893. }
  894. //-----------------------------------------------------------------------------
  895. // Purpose:
  896. //-----------------------------------------------------------------------------
  897. void C_BaseEntity::Precache( void )
  898. {
  899. }
  900. //-----------------------------------------------------------------------------
  901. // Purpose: Attach to entity
  902. // Input : *pEnt -
  903. // Output : Returns true on success, false on failure.
  904. //-----------------------------------------------------------------------------
  905. bool C_BaseEntity::Init( int entnum, int iSerialNum )
  906. {
  907. Assert( entnum >= 0 && entnum < NUM_ENT_ENTRIES );
  908. index = entnum;
  909. cl_entitylist->AddNetworkableEntity( GetIClientUnknown(), entnum, iSerialNum );
  910. CollisionProp()->CreatePartitionHandle();
  911. Interp_SetupMappings( GetVarMapping() );
  912. m_nCreationTick = gpGlobals->tickcount;
  913. return true;
  914. }
  915. //-----------------------------------------------------------------------------
  916. // Purpose:
  917. //-----------------------------------------------------------------------------
  918. bool C_BaseEntity::InitializeAsClientEntity( const char *pszModelName, RenderGroup_t renderGroup )
  919. {
  920. int nModelIndex;
  921. if ( pszModelName != NULL )
  922. {
  923. nModelIndex = modelinfo->GetModelIndex( pszModelName );
  924. if ( nModelIndex == -1 )
  925. {
  926. // Model could not be found
  927. Assert( !"Model could not be found, index is -1" );
  928. return false;
  929. }
  930. }
  931. else
  932. {
  933. nModelIndex = -1;
  934. }
  935. Interp_SetupMappings( GetVarMapping() );
  936. return InitializeAsClientEntityByIndex( nModelIndex, renderGroup );
  937. }
  938. //-----------------------------------------------------------------------------
  939. // Purpose:
  940. //-----------------------------------------------------------------------------
  941. bool C_BaseEntity::InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t renderGroup )
  942. {
  943. index = -1;
  944. // Setup model data.
  945. SetModelByIndex( iIndex );
  946. // Add the client entity to the master entity list.
  947. cl_entitylist->AddNonNetworkableEntity( GetIClientUnknown() );
  948. Assert( GetClientHandle() != ClientEntityList().InvalidHandle() );
  949. // Add the client entity to the renderable "leaf system." (Renderable)
  950. AddToLeafSystem( renderGroup );
  951. // Add the client entity to the spatial partition. (Collidable)
  952. CollisionProp()->CreatePartitionHandle();
  953. SpawnClientEntity();
  954. return true;
  955. }
  956. void C_BaseEntity::Term()
  957. {
  958. C_BaseEntity::PhysicsRemoveTouchedList( this );
  959. C_BaseEntity::PhysicsRemoveGroundList( this );
  960. DestroyAllDataObjects();
  961. #if !defined( NO_ENTITY_PREDICTION )
  962. // Remove from the predictables list
  963. if ( GetPredictable() || IsClientCreated() )
  964. {
  965. g_Predictables.RemoveFromPredictablesList( GetClientHandle() );
  966. }
  967. // If it's play simulated, remove from simulation list if the player still exists...
  968. if ( IsPlayerSimulated() && C_BasePlayer::GetLocalPlayer() )
  969. {
  970. C_BasePlayer::GetLocalPlayer()->RemoveFromPlayerSimulationList( this );
  971. }
  972. #endif
  973. if ( GetClientHandle() != INVALID_CLIENTENTITY_HANDLE )
  974. {
  975. if ( GetThinkHandle() != INVALID_THINK_HANDLE )
  976. {
  977. ClientThinkList()->RemoveThinkable( GetClientHandle() );
  978. }
  979. // Remove from the client entity list.
  980. ClientEntityList().RemoveEntity( GetClientHandle() );
  981. m_RefEHandle = INVALID_CLIENTENTITY_HANDLE;
  982. }
  983. // Are we in the partition?
  984. CollisionProp()->DestroyPartitionHandle();
  985. // If Client side only entity index will be -1
  986. if ( index != -1 )
  987. {
  988. beams->KillDeadBeams( this );
  989. }
  990. // Clean up the model instance
  991. DestroyModelInstance();
  992. // Clean up drawing
  993. RemoveFromLeafSystem();
  994. RemoveFromAimEntsList();
  995. }
  996. void C_BaseEntity::SetRefEHandle( const CBaseHandle &handle )
  997. {
  998. m_RefEHandle = handle;
  999. }
  1000. const CBaseHandle& C_BaseEntity::GetRefEHandle() const
  1001. {
  1002. return m_RefEHandle;
  1003. }
  1004. //-----------------------------------------------------------------------------
  1005. // Purpose: Free beams and destroy object
  1006. //-----------------------------------------------------------------------------
  1007. void C_BaseEntity::Release()
  1008. {
  1009. {
  1010. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true );
  1011. UnlinkFromHierarchy();
  1012. }
  1013. // Note that this must be called from here, not the destructor, because otherwise the
  1014. // vtable is hosed and the derived classes function is not going to get called!!!
  1015. if ( IsIntermediateDataAllocated() )
  1016. {
  1017. DestroyIntermediateData();
  1018. }
  1019. UpdateOnRemove();
  1020. delete this;
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. // Only meant to be called from subclasses.
  1024. // Returns true if instance valid, false otherwise
  1025. //-----------------------------------------------------------------------------
  1026. void C_BaseEntity::CreateModelInstance()
  1027. {
  1028. if ( m_ModelInstance == MODEL_INSTANCE_INVALID )
  1029. {
  1030. m_ModelInstance = modelrender->CreateInstance( this );
  1031. }
  1032. }
  1033. //-----------------------------------------------------------------------------
  1034. // Purpose:
  1035. //-----------------------------------------------------------------------------
  1036. void C_BaseEntity::DestroyModelInstance()
  1037. {
  1038. if (m_ModelInstance != MODEL_INSTANCE_INVALID)
  1039. {
  1040. modelrender->DestroyInstance( m_ModelInstance );
  1041. m_ModelInstance = MODEL_INSTANCE_INVALID;
  1042. }
  1043. }
  1044. void C_BaseEntity::SetRemovalFlag( bool bRemove )
  1045. {
  1046. if (bRemove)
  1047. m_iEFlags |= EFL_KILLME;
  1048. else
  1049. m_iEFlags &= ~EFL_KILLME;
  1050. }
  1051. //-----------------------------------------------------------------------------
  1052. // VPhysics objects..
  1053. //-----------------------------------------------------------------------------
  1054. int C_BaseEntity::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax )
  1055. {
  1056. IPhysicsObject *pPhys = VPhysicsGetObject();
  1057. if ( pPhys )
  1058. {
  1059. // multi-object entities must implement this function
  1060. Assert( !(pPhys->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY) );
  1061. if ( listMax > 0 )
  1062. {
  1063. pList[0] = pPhys;
  1064. return 1;
  1065. }
  1066. }
  1067. return 0;
  1068. }
  1069. bool C_BaseEntity::VPhysicsIsFlesh( void )
  1070. {
  1071. IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
  1072. int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) );
  1073. for ( int i = 0; i < count; i++ )
  1074. {
  1075. int material = pList[i]->GetMaterialIndex();
  1076. const surfacedata_t *pSurfaceData = physprops->GetSurfaceData( material );
  1077. // Is flesh ?, don't allow pickup
  1078. 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 )
  1079. return true;
  1080. }
  1081. return false;
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // Returns the health fraction
  1085. //-----------------------------------------------------------------------------
  1086. float C_BaseEntity::HealthFraction() const
  1087. {
  1088. if (GetMaxHealth() == 0)
  1089. return 1.0f;
  1090. float flFraction = (float)GetHealth() / (float)GetMaxHealth();
  1091. flFraction = clamp( flFraction, 0.0f, 1.0f );
  1092. return flFraction;
  1093. }
  1094. //-----------------------------------------------------------------------------
  1095. // Purpose: Retrieves the coordinate frame for this entity.
  1096. // Input : forward - Receives the entity's forward vector.
  1097. // right - Receives the entity's right vector.
  1098. // up - Receives the entity's up vector.
  1099. //-----------------------------------------------------------------------------
  1100. void C_BaseEntity::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const
  1101. {
  1102. // This call is necessary to cause m_rgflCoordinateFrame to be recomputed
  1103. const matrix3x4_t &entityToWorld = EntityToWorldTransform();
  1104. if (pForward != NULL)
  1105. {
  1106. MatrixGetColumn( entityToWorld, 0, *pForward );
  1107. }
  1108. if (pRight != NULL)
  1109. {
  1110. MatrixGetColumn( entityToWorld, 1, *pRight );
  1111. *pRight *= -1.0f;
  1112. }
  1113. if (pUp != NULL)
  1114. {
  1115. MatrixGetColumn( entityToWorld, 2, *pUp );
  1116. }
  1117. }
  1118. void C_BaseEntity::UpdateVisibility()
  1119. {
  1120. #ifdef TF_CLIENT_DLL
  1121. // TF prevents drawing of any entity attached to players that aren't items in the inventory of the player.
  1122. // This is to prevent servers creating fake cosmetic items and attaching them to players.
  1123. if ( !engine->IsPlayingDemo() )
  1124. {
  1125. static bool bIsStaging = ( engine->GetAppID() == 810 );
  1126. if ( !m_bValidatedOwner )
  1127. {
  1128. bool bRetry = false;
  1129. // Check it the first time we call update visibility (Source TV doesn't bother doing validation)
  1130. m_bDeemedInvalid = engine->IsHLTV() ? false : !ValidateEntityAttachedToPlayer( bRetry );
  1131. m_bValidatedOwner = !bRetry;
  1132. }
  1133. if ( m_bDeemedInvalid )
  1134. {
  1135. if ( bIsStaging )
  1136. {
  1137. if ( !m_bWasDeemedInvalid )
  1138. {
  1139. m_PreviousRenderMode = GetRenderMode();
  1140. m_PreviousRenderColor = GetRenderColor();
  1141. m_bWasDeemedInvalid = true;
  1142. }
  1143. SetRenderMode( kRenderTransColor );
  1144. SetRenderColor( 255, 0, 0, 200 );
  1145. }
  1146. else
  1147. {
  1148. RemoveFromLeafSystem();
  1149. return;
  1150. }
  1151. }
  1152. else if ( m_bWasDeemedInvalid )
  1153. {
  1154. if ( bIsStaging )
  1155. {
  1156. // We need to fix up the rendering.
  1157. SetRenderMode( m_PreviousRenderMode );
  1158. SetRenderColor( m_PreviousRenderColor.r, m_PreviousRenderColor.g, m_PreviousRenderColor.b, m_PreviousRenderColor.a );
  1159. }
  1160. m_bWasDeemedInvalid = false;
  1161. }
  1162. }
  1163. #endif
  1164. if ( ShouldDraw() && !IsDormant() && ( !ToolsEnabled() || IsEnabledInToolView() ) )
  1165. {
  1166. // add/update leafsystem
  1167. AddToLeafSystem();
  1168. }
  1169. else
  1170. {
  1171. // remove from leaf system
  1172. RemoveFromLeafSystem();
  1173. }
  1174. }
  1175. //-----------------------------------------------------------------------------
  1176. // Purpose: Returns whether object should render.
  1177. //-----------------------------------------------------------------------------
  1178. bool C_BaseEntity::ShouldDraw()
  1179. {
  1180. // Only test this in tf2
  1181. #if defined( INVASION_CLIENT_DLL )
  1182. // Let the client mode (like commander mode) reject drawing entities.
  1183. if (g_pClientMode && !g_pClientMode->ShouldDrawEntity(this) )
  1184. return false;
  1185. #endif
  1186. // Some rendermodes prevent rendering
  1187. if ( m_nRenderMode == kRenderNone )
  1188. return false;
  1189. return (model != 0) && !IsEffectActive(EF_NODRAW) && (index != 0);
  1190. }
  1191. bool C_BaseEntity::TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace )
  1192. {
  1193. return false;
  1194. }
  1195. bool C_BaseEntity::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr )
  1196. {
  1197. return false;
  1198. }
  1199. //-----------------------------------------------------------------------------
  1200. // Used when the collision prop is told to ask game code for the world-space surrounding box
  1201. //-----------------------------------------------------------------------------
  1202. void C_BaseEntity::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
  1203. {
  1204. // This should only be called if you're using USE_GAME_CODE on the server
  1205. // and you forgot to implement the client-side version of this method.
  1206. Assert(0);
  1207. }
  1208. //-----------------------------------------------------------------------------
  1209. // Purpose: Derived classes will have to write their own message cracking routines!!!
  1210. // Input : length -
  1211. // *data -
  1212. //-----------------------------------------------------------------------------
  1213. void C_BaseEntity::ReceiveMessage( int classID, bf_read &msg )
  1214. {
  1215. // BaseEntity doesn't have a base class we could relay this message to
  1216. Assert( classID == GetClientClass()->m_ClassID );
  1217. int messageType = msg.ReadByte();
  1218. switch( messageType )
  1219. {
  1220. case BASEENTITY_MSG_REMOVE_DECALS: RemoveAllDecals();
  1221. break;
  1222. }
  1223. }
  1224. void* C_BaseEntity::GetDataTableBasePtr()
  1225. {
  1226. return this;
  1227. }
  1228. //-----------------------------------------------------------------------------
  1229. // Should this object cast shadows?
  1230. //-----------------------------------------------------------------------------
  1231. ShadowType_t C_BaseEntity::ShadowCastType()
  1232. {
  1233. if (IsEffectActive(EF_NODRAW | EF_NOSHADOW))
  1234. return SHADOWS_NONE;
  1235. int modelType = modelinfo->GetModelType( model );
  1236. return (modelType == mod_studio) ? SHADOWS_RENDER_TO_TEXTURE : SHADOWS_NONE;
  1237. }
  1238. //-----------------------------------------------------------------------------
  1239. // Per-entity shadow cast distance + direction
  1240. //-----------------------------------------------------------------------------
  1241. bool C_BaseEntity::GetShadowCastDistance( float *pDistance, ShadowType_t shadowType ) const
  1242. {
  1243. if ( m_flShadowCastDistance != 0.0f )
  1244. {
  1245. *pDistance = m_flShadowCastDistance;
  1246. return true;
  1247. }
  1248. return false;
  1249. }
  1250. //-----------------------------------------------------------------------------
  1251. // Purpose:
  1252. //-----------------------------------------------------------------------------
  1253. C_BaseEntity *C_BaseEntity::GetShadowUseOtherEntity( void ) const
  1254. {
  1255. return m_ShadowDirUseOtherEntity;
  1256. }
  1257. //-----------------------------------------------------------------------------
  1258. // Purpose:
  1259. //-----------------------------------------------------------------------------
  1260. void C_BaseEntity::SetShadowUseOtherEntity( C_BaseEntity *pEntity )
  1261. {
  1262. m_ShadowDirUseOtherEntity = pEntity;
  1263. }
  1264. CInterpolatedVar< QAngle >& C_BaseEntity::GetRotationInterpolator()
  1265. {
  1266. return m_iv_angRotation;
  1267. }
  1268. CInterpolatedVar< Vector >& C_BaseEntity::GetOriginInterpolator()
  1269. {
  1270. return m_iv_vecOrigin;
  1271. }
  1272. //-----------------------------------------------------------------------------
  1273. // Purpose: Return a per-entity shadow cast direction
  1274. //-----------------------------------------------------------------------------
  1275. bool C_BaseEntity::GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const
  1276. {
  1277. if ( m_ShadowDirUseOtherEntity )
  1278. return m_ShadowDirUseOtherEntity->GetShadowCastDirection( pDirection, shadowType );
  1279. return false;
  1280. }
  1281. //-----------------------------------------------------------------------------
  1282. // Should this object receive shadows?
  1283. //-----------------------------------------------------------------------------
  1284. bool C_BaseEntity::ShouldReceiveProjectedTextures( int flags )
  1285. {
  1286. Assert( flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK );
  1287. if ( IsEffectActive( EF_NODRAW ) )
  1288. return false;
  1289. if( flags & SHADOW_FLAGS_FLASHLIGHT )
  1290. {
  1291. if ( GetRenderMode() > kRenderNormal && GetRenderColor().a == 0 )
  1292. return false;
  1293. return true;
  1294. }
  1295. Assert( flags & SHADOW_FLAGS_SHADOW );
  1296. if ( IsEffectActive( EF_NORECEIVESHADOW ) )
  1297. return false;
  1298. if (modelinfo->GetModelType( model ) == mod_studio)
  1299. return false;
  1300. return true;
  1301. }
  1302. //-----------------------------------------------------------------------------
  1303. // Shadow-related methods
  1304. //-----------------------------------------------------------------------------
  1305. bool C_BaseEntity::IsShadowDirty( )
  1306. {
  1307. return IsEFlagSet( EFL_DIRTY_SHADOWUPDATE );
  1308. }
  1309. void C_BaseEntity::MarkShadowDirty( bool bDirty )
  1310. {
  1311. if ( bDirty )
  1312. {
  1313. AddEFlags( EFL_DIRTY_SHADOWUPDATE );
  1314. }
  1315. else
  1316. {
  1317. RemoveEFlags( EFL_DIRTY_SHADOWUPDATE );
  1318. }
  1319. }
  1320. IClientRenderable *C_BaseEntity::GetShadowParent()
  1321. {
  1322. C_BaseEntity *pParent = GetMoveParent();
  1323. return pParent ? pParent->GetClientRenderable() : NULL;
  1324. }
  1325. IClientRenderable *C_BaseEntity::FirstShadowChild()
  1326. {
  1327. C_BaseEntity *pChild = FirstMoveChild();
  1328. return pChild ? pChild->GetClientRenderable() : NULL;
  1329. }
  1330. IClientRenderable *C_BaseEntity::NextShadowPeer()
  1331. {
  1332. C_BaseEntity *pPeer = NextMovePeer();
  1333. return pPeer ? pPeer->GetClientRenderable() : NULL;
  1334. }
  1335. //-----------------------------------------------------------------------------
  1336. // Purpose: Returns index into entities list for this entity
  1337. // Output : Index
  1338. //-----------------------------------------------------------------------------
  1339. int C_BaseEntity::entindex( void ) const
  1340. {
  1341. return index;
  1342. }
  1343. int C_BaseEntity::GetSoundSourceIndex() const
  1344. {
  1345. #ifdef _DEBUG
  1346. if ( index != -1 )
  1347. {
  1348. Assert( index == GetRefEHandle().GetEntryIndex() );
  1349. }
  1350. #endif
  1351. return GetRefEHandle().GetEntryIndex();
  1352. }
  1353. //-----------------------------------------------------------------------------
  1354. // Get render origin and angles
  1355. //-----------------------------------------------------------------------------
  1356. const Vector& C_BaseEntity::GetRenderOrigin( void )
  1357. {
  1358. return GetAbsOrigin();
  1359. }
  1360. const QAngle& C_BaseEntity::GetRenderAngles( void )
  1361. {
  1362. return GetAbsAngles();
  1363. }
  1364. const matrix3x4_t &C_BaseEntity::RenderableToWorldTransform()
  1365. {
  1366. return EntityToWorldTransform();
  1367. }
  1368. IPVSNotify* C_BaseEntity::GetPVSNotifyInterface()
  1369. {
  1370. return NULL;
  1371. }
  1372. //-----------------------------------------------------------------------------
  1373. // Purpose:
  1374. // Input : theMins -
  1375. // theMaxs -
  1376. //-----------------------------------------------------------------------------
  1377. void C_BaseEntity::GetRenderBounds( Vector& theMins, Vector& theMaxs )
  1378. {
  1379. int nModelType = modelinfo->GetModelType( model );
  1380. if (nModelType == mod_studio || nModelType == mod_brush)
  1381. {
  1382. modelinfo->GetModelRenderBounds( GetModel(), theMins, theMaxs );
  1383. }
  1384. else
  1385. {
  1386. // By default, we'll just snack on the collision bounds, transform
  1387. // them into entity-space, and call it a day.
  1388. if ( GetRenderAngles() == CollisionProp()->GetCollisionAngles() )
  1389. {
  1390. theMins = CollisionProp()->OBBMins();
  1391. theMaxs = CollisionProp()->OBBMaxs();
  1392. }
  1393. else
  1394. {
  1395. Assert( CollisionProp()->GetCollisionAngles() == vec3_angle );
  1396. if ( IsPointSized() )
  1397. {
  1398. //theMins = CollisionProp()->GetCollisionOrigin();
  1399. //theMaxs = theMins;
  1400. theMins = theMaxs = vec3_origin;
  1401. }
  1402. else
  1403. {
  1404. // NOTE: This shouldn't happen! Or at least, I haven't run
  1405. // into a valid case where it should yet.
  1406. // Assert(0);
  1407. IRotateAABB( EntityToWorldTransform(), CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), theMins, theMaxs );
  1408. }
  1409. }
  1410. }
  1411. }
  1412. void C_BaseEntity::GetRenderBoundsWorldspace( Vector& mins, Vector& maxs )
  1413. {
  1414. DefaultRenderBoundsWorldspace( this, mins, maxs );
  1415. }
  1416. void C_BaseEntity::GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType )
  1417. {
  1418. m_EntClientFlags |= ENTCLIENTFLAG_GETTINGSHADOWRENDERBOUNDS;
  1419. GetRenderBounds( mins, maxs );
  1420. m_EntClientFlags &= ~ENTCLIENTFLAG_GETTINGSHADOWRENDERBOUNDS;
  1421. }
  1422. //-----------------------------------------------------------------------------
  1423. // Purpose: Last received origin
  1424. // Output : const float
  1425. //-----------------------------------------------------------------------------
  1426. const Vector& C_BaseEntity::GetAbsOrigin( void ) const
  1427. {
  1428. //Assert( s_bAbsQueriesValid );
  1429. const_cast<C_BaseEntity*>(this)->CalcAbsolutePosition();
  1430. return m_vecAbsOrigin;
  1431. }
  1432. //-----------------------------------------------------------------------------
  1433. // Purpose: Last received angles
  1434. // Output : const
  1435. //-----------------------------------------------------------------------------
  1436. const QAngle& C_BaseEntity::GetAbsAngles( void ) const
  1437. {
  1438. //Assert( s_bAbsQueriesValid );
  1439. const_cast<C_BaseEntity*>(this

Large files files are truncated, but you can click here to view the full file