Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1220 lines
34 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Clones a physics object (usually with a matrix transform applied)
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "physicsshadowclone.h"
  9. #include "portal_util_shared.h"
  10. #include "vphysics/object_hash.h"
  11. #include "trains.h"
  12. #include "props.h"
  13. #include "model_types.h"
  14. #include "portal/weapon_physcannon.h" //grab controllers
  15. #include "PortalSimulation.h"
  16. #define MAX_SHADOW_CLONE_COUNT 200
  17. static int g_iShadowCloneCount = 0;
  18. ConVar sv_debug_physicsshadowclones("sv_debug_physicsshadowclones", "0", FCVAR_REPLICATED );
  19. ConVar sv_use_shadow_clones( "sv_use_shadow_clones", "1", FCVAR_REPLICATED | FCVAR_CHEAT ); //should we create shadow clones?
  20. LINK_ENTITY_TO_CLASS( physicsshadowclone, CPhysicsShadowClone );
  21. static CUtlVector<CPhysicsShadowClone *> s_ActiveShadowClones;
  22. CUtlVector<CPhysicsShadowClone *> const &CPhysicsShadowClone::g_ShadowCloneList = s_ActiveShadowClones;
  23. static bool s_IsShadowClone[MAX_EDICTS] = { false };
  24. static CPhysicsShadowCloneLL *s_EntityClones[MAX_EDICTS] = { NULL };
  25. struct ShadowCloneLLEntryManager
  26. {
  27. CPhysicsShadowCloneLL m_ShadowCloneLLEntries[MAX_SHADOW_CLONE_COUNT];
  28. CPhysicsShadowCloneLL *m_pFreeShadowCloneLLEntries[MAX_SHADOW_CLONE_COUNT];
  29. int m_iUsedEntryIndex;
  30. ShadowCloneLLEntryManager( void )
  31. {
  32. m_iUsedEntryIndex = 0;
  33. for( int i = 0; i != MAX_SHADOW_CLONE_COUNT; ++i )
  34. {
  35. m_pFreeShadowCloneLLEntries[i] = &m_ShadowCloneLLEntries[i];
  36. }
  37. }
  38. inline CPhysicsShadowCloneLL *Alloc( void )
  39. {
  40. return m_pFreeShadowCloneLLEntries[m_iUsedEntryIndex++];
  41. }
  42. inline void Free( CPhysicsShadowCloneLL *pFree )
  43. {
  44. m_pFreeShadowCloneLLEntries[--m_iUsedEntryIndex] = pFree;
  45. }
  46. };
  47. static ShadowCloneLLEntryManager s_SCLLManager;
  48. CPhysicsShadowClone::CPhysicsShadowClone( void )
  49. {
  50. m_matrixShadowTransform.Identity();
  51. m_matrixShadowTransform_Inverse.Identity();
  52. m_bShadowTransformIsIdentity = true;
  53. s_ActiveShadowClones.AddToTail( this );
  54. }
  55. CPhysicsShadowClone::~CPhysicsShadowClone( void )
  56. {
  57. VPhysicsDestroyObject();
  58. VPhysicsSetObject( NULL );
  59. m_hClonedEntity = NULL;
  60. s_ActiveShadowClones.FindAndRemove( this ); //also removed in UpdateOnRemove()
  61. Assert( s_IsShadowClone[entindex()] == true );
  62. s_IsShadowClone[entindex()] = false;
  63. }
  64. void CPhysicsShadowClone::UpdateOnRemove( void )
  65. {
  66. CBaseEntity *pSource = m_hClonedEntity;
  67. if( pSource )
  68. {
  69. CPhysicsShadowCloneLL *pCloneListHead = s_EntityClones[pSource->entindex()];
  70. Assert( pCloneListHead != NULL );
  71. CPhysicsShadowCloneLL *pFind = pCloneListHead;
  72. CPhysicsShadowCloneLL *pLast = pFind;
  73. while( pFind->pClone != this )
  74. {
  75. pLast = pFind;
  76. Assert( pFind->pNext != NULL );
  77. pFind = pFind->pNext;
  78. }
  79. if( pFind == pCloneListHead )
  80. {
  81. s_EntityClones[pSource->entindex()] = pFind->pNext;
  82. }
  83. else
  84. {
  85. pLast->pNext = pFind->pNext;
  86. }
  87. s_SCLLManager.Free( pFind );
  88. }
  89. #ifdef _DEBUG
  90. else
  91. {
  92. //verify that it didn't weasel into a list somewhere and get left behind
  93. for( int i = 0; i != MAX_SHADOW_CLONE_COUNT; ++i )
  94. {
  95. CPhysicsShadowCloneLL *pCloneSearch = s_EntityClones[i];
  96. while( pCloneSearch )
  97. {
  98. Assert( pCloneSearch->pClone != this );
  99. pCloneSearch = pCloneSearch->pNext;
  100. }
  101. }
  102. }
  103. #endif
  104. VPhysicsDestroyObject();
  105. VPhysicsSetObject( NULL );
  106. m_hClonedEntity = NULL;
  107. s_ActiveShadowClones.FindAndRemove( this ); //also removed in Destructor
  108. BaseClass::UpdateOnRemove();
  109. }
  110. void CPhysicsShadowClone::Spawn( void )
  111. {
  112. AddFlag( FL_DONTTOUCH );
  113. AddEffects( EF_NODRAW | EF_NOSHADOW | EF_NORECEIVESHADOW );
  114. FullSync( false );
  115. m_bInAssumedSyncState = false;
  116. BaseClass::Spawn();
  117. s_IsShadowClone[entindex()] = true;
  118. }
  119. void CPhysicsShadowClone::FullSync( bool bAllowAssumedSync )
  120. {
  121. Assert( IsMarkedForDeletion() == false );
  122. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  123. if( pClonedEntity == NULL )
  124. {
  125. AssertMsg( VPhysicsGetObject() != NULL, "Been linkless for more than this update, something should have killed this clone." );
  126. SetMoveType( MOVETYPE_NONE );
  127. SetSolid( SOLID_NONE );
  128. SetSolidFlags( 0 );
  129. SetCollisionGroup( COLLISION_GROUP_NONE );
  130. VPhysicsDestroyObject();
  131. return;
  132. }
  133. SetGroundEntity( NULL );
  134. bool bIsSynced = bAllowAssumedSync;
  135. bool bBigChanges = true; //assume there are, and be proven wrong
  136. if( bAllowAssumedSync )
  137. {
  138. IPhysicsObject *pSourceObjects[1024];
  139. int iObjectCount = pClonedEntity->VPhysicsGetObjectList( pSourceObjects, 1024 );
  140. //scan for really big differences that would definitely require a full sync
  141. bBigChanges = ( iObjectCount != m_CloneLinks.Count() );
  142. if( !bBigChanges )
  143. {
  144. for( int i = 0; i != iObjectCount; ++i )
  145. {
  146. IPhysicsObject *pSourcePhysics = pSourceObjects[i];
  147. IPhysicsObject *pClonedPhysics = m_CloneLinks[i].pClone;
  148. if( (pSourcePhysics != m_CloneLinks[i].pSource) ||
  149. (pSourcePhysics->IsCollisionEnabled() != pClonedPhysics->IsCollisionEnabled()) )
  150. {
  151. bBigChanges = true;
  152. bIsSynced = false;
  153. break;
  154. }
  155. Vector ptSourcePosition, ptClonePosition;
  156. pSourcePhysics->GetPosition( &ptSourcePosition, NULL );
  157. if( !m_bShadowTransformIsIdentity )
  158. ptSourcePosition = m_matrixShadowTransform * ptSourcePosition;
  159. pClonedPhysics->GetPosition( &ptClonePosition, NULL );
  160. if( (ptClonePosition - ptSourcePosition).LengthSqr() > 2500.0f )
  161. {
  162. bBigChanges = true;
  163. bIsSynced = false;
  164. break;
  165. }
  166. //Vector vSourceVelocity, vCloneVelocity;
  167. if( !pSourcePhysics->IsAsleep() ) //only allow full syncrosity if the source entity is entirely asleep
  168. bIsSynced = false;
  169. if( m_bInAssumedSyncState && !pClonedPhysics->IsAsleep() )
  170. bIsSynced = false;
  171. }
  172. }
  173. else
  174. {
  175. bIsSynced = false;
  176. }
  177. bIsSynced = false;
  178. if( bIsSynced )
  179. {
  180. //good enough to skip a full update
  181. if( !m_bInAssumedSyncState )
  182. {
  183. //do one last sync
  184. PartialSync( true );
  185. //if we don't do this, objects just fall out of the world (it happens, I swear)
  186. for( int i = m_CloneLinks.Count(); --i >= 0; )
  187. {
  188. if( (m_CloneLinks[i].pSource->GetShadowController() == NULL) && m_CloneLinks[i].pClone->IsMotionEnabled() )
  189. {
  190. //m_CloneLinks[i].pClone->SetVelocityInstantaneous( &vec3_origin, &vec3_origin );
  191. //m_CloneLinks[i].pClone->SetVelocity( &vec3_origin, &vec3_origin );
  192. m_CloneLinks[i].pClone->EnableGravity( false );
  193. m_CloneLinks[i].pClone->EnableMotion( false );
  194. m_CloneLinks[i].pClone->Sleep();
  195. }
  196. }
  197. m_bInAssumedSyncState = true;
  198. }
  199. if( sv_debug_physicsshadowclones.GetBool() )
  200. DrawDebugOverlayForShadowClone( this );
  201. return;
  202. }
  203. }
  204. m_bInAssumedSyncState = false;
  205. //past this point, we're committed to a broad update
  206. if( bBigChanges )
  207. {
  208. MoveType_t sourceMoveType = pClonedEntity->GetMoveType();
  209. IPhysicsObject *pPhysObject = pClonedEntity->VPhysicsGetObject();
  210. if( (sourceMoveType == MOVETYPE_CUSTOM) ||
  211. (sourceMoveType == MOVETYPE_STEP) ||
  212. (sourceMoveType == MOVETYPE_WALK) ||
  213. (pPhysObject &&
  214. (
  215. (pPhysObject->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ||
  216. (pPhysObject->GetShadowController() != NULL)
  217. )
  218. )
  219. )
  220. {
  221. //#ifdef _DEBUG
  222. SetMoveType( MOVETYPE_NONE ); //to kill an assert
  223. //#endif
  224. //PUSH should be used sparingly, you can't stand on a MOVETYPE_PUSH object :/
  225. SetMoveType( MOVETYPE_VPHYSICS, pClonedEntity->GetMoveCollide() ); //either an unclonable movetype, or a shadow/held object
  226. }
  227. /*else if(sourceMoveType == MOVETYPE_STEP)
  228. {
  229. //SetMoveType( MOVETYPE_NONE ); //to kill an assert
  230. SetMoveType( MOVETYPE_VPHYSICS, pClonedEntity->GetMoveCollide() );
  231. }*/
  232. else
  233. {
  234. //if( m_bShadowTransformIsIdentity )
  235. SetMoveType( sourceMoveType, pClonedEntity->GetMoveCollide() );
  236. //else
  237. //{
  238. // SetMoveType( MOVETYPE_NONE ); //to kill an assert
  239. // SetMoveType( MOVETYPE_PUSH, pClonedEntity->GetMoveCollide() );
  240. //}
  241. }
  242. SolidType_t sourceSolidType = pClonedEntity->GetSolid();
  243. if( sourceSolidType == SOLID_BBOX )
  244. SetSolid( SOLID_VPHYSICS );
  245. else
  246. SetSolid( sourceSolidType );
  247. //SetSolid( SOLID_VPHYSICS );
  248. SetElasticity( pClonedEntity->GetElasticity() );
  249. SetFriction( pClonedEntity->GetFriction() );
  250. int iSolidFlags = pClonedEntity->GetSolidFlags() | FSOLID_CUSTOMRAYTEST;
  251. if( m_bShadowTransformIsIdentity )
  252. iSolidFlags |= FSOLID_CUSTOMBOXTEST; //need this at least for the player or they get stuck in themselves
  253. else
  254. iSolidFlags &= ~FSOLID_FORCE_WORLD_ALIGNED;
  255. /*if( pClonedEntity->IsPlayer() )
  256. {
  257. iSolidFlags |= FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST;
  258. }*/
  259. SetSolidFlags( iSolidFlags );
  260. SetEffects( pClonedEntity->GetEffects() | (EF_NODRAW | EF_NOSHADOW | EF_NORECEIVESHADOW) );
  261. SetCollisionGroup( pClonedEntity->GetCollisionGroup() );
  262. SetModelIndex( pClonedEntity->GetModelIndex() );
  263. SetModelName( pClonedEntity->GetModelName() );
  264. if( modelinfo->GetModelType( pClonedEntity->GetModel() ) == mod_studio )
  265. SetModel( STRING( pClonedEntity->GetModelName() ) );
  266. CCollisionProperty *pClonedCollisionProp = pClonedEntity->CollisionProp();
  267. SetSize( pClonedCollisionProp->OBBMins(), pClonedCollisionProp->OBBMaxs() );
  268. }
  269. FullSyncClonedPhysicsObjects( bBigChanges );
  270. SyncEntity( true );
  271. if( bBigChanges )
  272. CollisionRulesChanged();
  273. if( sv_debug_physicsshadowclones.GetBool() )
  274. DrawDebugOverlayForShadowClone( this );
  275. }
  276. // this enables a fast/cheap version of teleporting that is less accurate WRT physics objects' contacts after small teleportations
  277. ConVar fast_teleport_enable("fast_teleport_enable", "1");
  278. void CPhysicsShadowClone::SyncEntity( bool bPullChanges )
  279. {
  280. m_bShouldUpSync = false;
  281. CBaseEntity *pSource, *pDest;
  282. VMatrix *pTransform;
  283. if( bPullChanges )
  284. {
  285. pSource = m_hClonedEntity.Get();
  286. pDest = this;
  287. pTransform = &m_matrixShadowTransform;
  288. if( pSource == NULL )
  289. return;
  290. }
  291. else
  292. {
  293. pSource = this;
  294. pDest = m_hClonedEntity.Get();
  295. pTransform = &m_matrixShadowTransform_Inverse;
  296. if( pDest == NULL )
  297. return;
  298. }
  299. Vector ptOrigin, vVelocity;
  300. QAngle qAngles;
  301. ptOrigin = pSource->GetAbsOrigin();
  302. qAngles = pSource->IsPlayer() ? vec3_angle : pSource->GetAbsAngles();
  303. vVelocity = pSource->GetAbsVelocity();
  304. if( !m_bShadowTransformIsIdentity )
  305. {
  306. ptOrigin = (*pTransform) * ptOrigin;
  307. qAngles = TransformAnglesToWorldSpace( qAngles, pTransform->As3x4() );
  308. vVelocity = pTransform->ApplyRotation( vVelocity );
  309. }
  310. //else
  311. //{
  312. // pDest->SetGroundEntity( pSource->GetGroundEntity() );
  313. //}
  314. QAngle qDiff;
  315. RotationDelta( pDest->GetAbsAngles(), qAngles, &qDiff );
  316. if( (ptOrigin - pDest->GetAbsOrigin()).LengthSqr() > 0.0001f || qDiff.LengthSqr() > 0.0001f )
  317. {
  318. pDest->Teleport( &ptOrigin, &qAngles, NULL, !fast_teleport_enable.GetBool() );
  319. }
  320. if( vVelocity != pDest->GetAbsVelocity() )
  321. {
  322. //pDest->AddEffects( EF_NOINTERP );
  323. pDest->SetAbsVelocity( vec3_origin ); //the two step process helps, I don't know why, but it does
  324. pDest->ApplyAbsVelocityImpulse( vVelocity );
  325. }
  326. }
  327. static void FullSyncPhysicsObject( IPhysicsObject *pSource, IPhysicsObject *pDest, const VMatrix *pTransform, bool bTeleport )
  328. {
  329. CGrabController *pGrabController = NULL;
  330. if( !pSource->IsAsleep() )
  331. pDest->Wake();
  332. float fSavedMass = 0.0f, fSavedRotationalDamping; //setting mass to 0.0f purely to kill a warning that I can't seem to kill with pragmas
  333. if( pSource->GetGameFlags() & FVPHYSICS_PLAYER_HELD )
  334. {
  335. //CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
  336. //Assert( pPlayer );
  337. CBaseEntity *pLookingForEntity = (CBaseEntity *)pSource->GetGameData();
  338. CBasePlayer *pHoldingPlayer = GetPlayerHoldingEntity( pLookingForEntity );
  339. if( pHoldingPlayer )
  340. {
  341. pGrabController = GetGrabControllerForPlayer( pHoldingPlayer );
  342. if ( !pGrabController )
  343. pGrabController = GetGrabControllerForPhysCannon( pHoldingPlayer->GetActiveWeapon() );
  344. }
  345. AssertMsg( pGrabController, "Physics object is held, but we can't find the holding controller." );
  346. GetSavedParamsForCarriedPhysObject( pGrabController, pSource, &fSavedMass, &fSavedRotationalDamping );
  347. }
  348. //Boiler plate
  349. {
  350. pDest->SetGameIndex( pSource->GetGameIndex() ); //what's it do?
  351. pDest->SetCallbackFlags( pSource->GetCallbackFlags() ); //wise?
  352. pDest->SetGameFlags( pSource->GetGameFlags() | FVPHYSICS_NO_SELF_COLLISIONS | FVPHYSICS_IS_SHADOWCLONE );
  353. pDest->SetMaterialIndex( pSource->GetMaterialIndex() );
  354. pDest->SetContents( pSource->GetContents() );
  355. pDest->SyncWith( pSource );
  356. }
  357. //Damping
  358. {
  359. float fSpeedDamp, fRotDamp;
  360. if( pGrabController )
  361. {
  362. pSource->GetDamping( &fSpeedDamp, NULL );
  363. pDest->SetDamping( &fSpeedDamp, &fSavedRotationalDamping );
  364. }
  365. else
  366. {
  367. pSource->GetDamping( &fSpeedDamp, &fRotDamp );
  368. pDest->SetDamping( &fSpeedDamp, &fRotDamp );
  369. }
  370. }
  371. //stuff that we really care about
  372. {
  373. if( pGrabController )
  374. {
  375. pDest->SetMass( fSavedMass );
  376. }
  377. else
  378. {
  379. float flMass = pSource->GetMass();
  380. if ( pDest->GetMass() != flMass )
  381. {
  382. pDest->SetMass( flMass );
  383. }
  384. }
  385. Vector vInertia;
  386. Vector vVelocity, vAngularVelocity;
  387. pSource->GetVelocity( &vVelocity, &vAngularVelocity );
  388. vInertia = pSource->GetInertia();
  389. if( pTransform )
  390. {
  391. vVelocity = pTransform->ApplyRotation( vVelocity );
  392. vAngularVelocity = pTransform->ApplyRotation( vAngularVelocity );
  393. }
  394. //avoid oversetting variables (I think that even setting them to the same value they already are disrupts the delicate physics balance)
  395. if( vInertia != pDest->GetInertia() )
  396. pDest->SetInertia( vInertia );
  397. //pDest->SetVelocityInstantaneous( &vec3_origin, &vec3_origin );
  398. //pDest->Sleep();
  399. Vector vDestVelocity, vDestAngularVelocity;
  400. pDest->GetVelocity( &vDestVelocity, &vDestAngularVelocity );
  401. if( (vVelocity != vDestVelocity) || (vAngularVelocity != vDestAngularVelocity) )
  402. pDest->SetVelocityInstantaneous( &vVelocity, &vAngularVelocity );
  403. IPhysicsShadowController *pSourceController = pSource->GetShadowController();
  404. if( pSourceController == NULL )
  405. {
  406. if( pDest->GetShadowController() != NULL )
  407. {
  408. //we don't need a shadow controller anymore
  409. pDest->RemoveShadowController();
  410. }
  411. if ( bTeleport )
  412. {
  413. Vector ptOrigin;
  414. QAngle qAngles;
  415. pSource->GetPosition( &ptOrigin, &qAngles );
  416. Vector ptDestOrigin;
  417. QAngle qDestAngles;
  418. pDest->GetPosition( &ptDestOrigin, &qDestAngles );
  419. if( pTransform )
  420. {
  421. ptOrigin = (*pTransform) * ptOrigin;
  422. qAngles = TransformAnglesToWorldSpace( qAngles, pTransform->As3x4() );
  423. }
  424. if( (ptOrigin != ptDestOrigin) || (qAngles != qDestAngles) )
  425. {
  426. pDest->SetPosition( ptOrigin, qAngles, bTeleport );
  427. }
  428. }
  429. }
  430. else
  431. {
  432. IPhysicsShadowController *pDestController = pDest->GetShadowController();
  433. if( pDestController == NULL )
  434. {
  435. //we need a shadow controller
  436. float fMaxSpeed, fMaxAngularSpeed;
  437. pSourceController->GetMaxSpeed( &fMaxSpeed, &fMaxAngularSpeed );
  438. pDest->SetShadow( fMaxSpeed, fMaxAngularSpeed, pSourceController->AllowsTranslation(), pSourceController->AllowsRotation() );
  439. pDestController = pDest->GetShadowController();
  440. pDestController->SetTeleportDistance( pSourceController->GetTeleportDistance() );
  441. pDestController->SetPhysicallyControlled( pSourceController->IsPhysicallyControlled() );
  442. }
  443. //sync shadow controllers
  444. float fTimeOffset;
  445. Vector ptTargetPosition;
  446. QAngle qTargetAngles;
  447. fTimeOffset = pSourceController->GetTargetPosition( &ptTargetPosition, &qTargetAngles );
  448. if( pTransform )
  449. {
  450. ptTargetPosition = (*pTransform) * ptTargetPosition;
  451. qTargetAngles = TransformAnglesToWorldSpace( qTargetAngles, pTransform->As3x4() );
  452. }
  453. pDestController->Update( ptTargetPosition, qTargetAngles, fTimeOffset );
  454. }
  455. }
  456. //pDest->RecheckContactPoints();
  457. }
  458. static void PartialSyncPhysicsObject( IPhysicsObject *pSource, IPhysicsObject *pDest, const VMatrix *pTransform )
  459. {
  460. Vector ptOrigin, vVelocity, vAngularVelocity, vInertia;
  461. QAngle qAngles;
  462. pSource->GetPosition( &ptOrigin, &qAngles );
  463. pSource->GetVelocity( &vVelocity, &vAngularVelocity );
  464. vInertia = pSource->GetInertia();
  465. if( pTransform )
  466. {
  467. #if 0
  468. //pDest->SetPositionMatrix( matTransform.As3x4(), true ); //works like we think?
  469. #else
  470. ptOrigin = (*pTransform) * ptOrigin;
  471. qAngles = TransformAnglesToWorldSpace( qAngles, pTransform->As3x4() );
  472. vVelocity = pTransform->ApplyRotation( vVelocity );
  473. vAngularVelocity = pTransform->ApplyRotation( vAngularVelocity );
  474. #endif
  475. }
  476. //avoid oversetting variables (I think that even setting them to the same value they already are disrupts the delicate physics balance)
  477. if( vInertia != pDest->GetInertia() )
  478. pDest->SetInertia( vInertia );
  479. Vector ptDestOrigin, vDestVelocity, vDestAngularVelocity;
  480. QAngle qDestAngles;
  481. pDest->GetPosition( &ptDestOrigin, &qDestAngles );
  482. pDest->GetVelocity( &vDestVelocity, &vDestAngularVelocity );
  483. if( (ptOrigin != ptDestOrigin) || (qAngles != qDestAngles) )
  484. pDest->SetPosition( ptOrigin, qAngles, false );
  485. if( (vVelocity != vDestVelocity) || (vAngularVelocity != vDestAngularVelocity) )
  486. pDest->SetVelocity( &vVelocity, &vAngularVelocity );
  487. pDest->EnableCollisions( pSource->IsCollisionEnabled() );
  488. }
  489. IPhysicsObject *ClonePhysObject( IPhysicsObject *pSource, IPhysicsEnvironment *pDestEnvironment, void *pCloneGameData )
  490. {
  491. unsigned int size = physenv->GetObjectSerializeSize(pSource);
  492. byte *pBuffer = (byte *)stackalloc(size);
  493. memset( pBuffer, 0, size );
  494. physenv->SerializeObjectToBuffer( pSource, pBuffer, size ); //this should work across physics environments because the serializer doesn't write anything about itself to the template
  495. return pDestEnvironment->UnserializeObjectFromBuffer( pCloneGameData, pBuffer, size, false ); //unserializer has to be in the target environment
  496. }
  497. void CPhysicsShadowClone::FullSyncClonedPhysicsObjects( bool bTeleport )
  498. {
  499. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  500. if( pClonedEntity == NULL )
  501. {
  502. VPhysicsDestroyObject();
  503. return;
  504. }
  505. VMatrix *pTransform;
  506. if( m_bShadowTransformIsIdentity )
  507. pTransform = NULL;
  508. else
  509. pTransform = &m_matrixShadowTransform;
  510. IPhysicsObject *(pSourceObjects[1024]);
  511. int iObjectCount = pClonedEntity->VPhysicsGetObjectList( pSourceObjects, 1024 );
  512. //easy out if nothing has changed
  513. if( iObjectCount == m_CloneLinks.Count() )
  514. {
  515. int i;
  516. for( i = 0; i != iObjectCount; ++i )
  517. {
  518. if( pSourceObjects[i] == NULL )
  519. break;
  520. if( pSourceObjects[i] != m_CloneLinks[i].pSource )
  521. break;
  522. }
  523. if( i == iObjectCount ) //no changes
  524. {
  525. for( i = 0; i != iObjectCount; ++i )
  526. FullSyncPhysicsObject( m_CloneLinks[i].pSource, m_CloneLinks[i].pClone, pTransform, bTeleport );
  527. return;
  528. }
  529. }
  530. //copy the existing list of clone links to a temp array, we're going to be starting from scratch and copying links as we need them
  531. PhysicsObjectCloneLink_t *pExistingLinks = NULL;
  532. int iExistingLinkCount = m_CloneLinks.Count();
  533. if( iExistingLinkCount != 0 )
  534. {
  535. pExistingLinks = (PhysicsObjectCloneLink_t *)stackalloc( sizeof(PhysicsObjectCloneLink_t) * m_CloneLinks.Count() );
  536. memcpy( pExistingLinks, m_CloneLinks.Base(), sizeof(PhysicsObjectCloneLink_t) * m_CloneLinks.Count() );
  537. }
  538. m_CloneLinks.RemoveAll();
  539. //now, go over the object list we just got from the source entity, and either copy or create links as necessary
  540. int i;
  541. for( i = 0; i != iObjectCount; ++i )
  542. {
  543. IPhysicsObject *pSource = pSourceObjects[i];
  544. if( pSource == NULL ) //this really shouldn't happen, but it does >_<
  545. continue;
  546. PhysicsObjectCloneLink_t cloneLink;
  547. int j;
  548. for( j = 0; j != iExistingLinkCount; ++j )
  549. {
  550. if( pExistingLinks[j].pSource == pSource )
  551. break;
  552. }
  553. if( j != iExistingLinkCount )
  554. {
  555. //copyable link found
  556. cloneLink = pExistingLinks[j];
  557. memset( &pExistingLinks[j], 0, sizeof( PhysicsObjectCloneLink_t ) ); //zero out this slot so we don't destroy it in cleanup
  558. }
  559. else
  560. {
  561. //no link found to copy, create a new one
  562. cloneLink.pSource = pSource;
  563. //apparently some collision code gets called on creation before we've set extra game flags, so we're going to cheat a bit and temporarily set our extra flags on the source
  564. unsigned int iOldGameFlags = pSource->GetGameFlags();
  565. pSource->SetGameFlags( iOldGameFlags | FVPHYSICS_IS_SHADOWCLONE );
  566. cloneLink.pClone = ClonePhysObject( pSource, m_pOwnerPhysEnvironment, this );
  567. assert( cloneLink.pClone ); //there should be absolutely no case where we can't clone a valid existing physics object
  568. pSource->SetGameFlags( iOldGameFlags );
  569. }
  570. FullSyncPhysicsObject( cloneLink.pSource, cloneLink.pClone, pTransform, bTeleport );
  571. //cloneLink.pClone->Wake();
  572. m_CloneLinks.AddToTail( cloneLink );
  573. }
  574. //now go over the existing links, if any of them haven't been nullified, they need to be deleted
  575. for( i = 0; i != iExistingLinkCount; ++i )
  576. {
  577. if( pExistingLinks[i].pClone )
  578. m_pOwnerPhysEnvironment->DestroyObject( pExistingLinks[i].pClone ); //also destroys shadow controller
  579. }
  580. VPhysicsSetObject( NULL );
  581. IPhysicsObject *pSource = m_hClonedEntity->VPhysicsGetObject();
  582. for( i = m_CloneLinks.Count(); --i >= 0; )
  583. {
  584. if( m_CloneLinks[i].pSource == pSource )
  585. {
  586. //m_CloneLinks[i].pClone->Wake();
  587. VPhysicsSetObject( m_CloneLinks[i].pClone );
  588. break;
  589. }
  590. }
  591. if( (i < 0) && (m_CloneLinks.Count() != 0) )
  592. {
  593. VPhysicsSetObject( m_CloneLinks[0].pClone );
  594. }
  595. stackfree( pExistingLinks );
  596. //CollisionRulesChanged();
  597. }
  598. void CPhysicsShadowClone::PartialSync( bool bPullChanges )
  599. {
  600. VMatrix *pTransform;
  601. if( bPullChanges )
  602. {
  603. if( m_bShadowTransformIsIdentity )
  604. pTransform = NULL;
  605. else
  606. pTransform = &m_matrixShadowTransform;
  607. for( int i = m_CloneLinks.Count(); --i >= 0; )
  608. PartialSyncPhysicsObject( m_CloneLinks[i].pSource, m_CloneLinks[i].pClone, pTransform );
  609. }
  610. else
  611. {
  612. if( m_bShadowTransformIsIdentity )
  613. pTransform = NULL;
  614. else
  615. pTransform = &m_matrixShadowTransform_Inverse;
  616. for( int i = m_CloneLinks.Count(); --i >= 0; )
  617. PartialSyncPhysicsObject( m_CloneLinks[i].pClone, m_CloneLinks[i].pSource, pTransform );
  618. }
  619. SyncEntity( bPullChanges );
  620. }
  621. int CPhysicsShadowClone::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax )
  622. {
  623. int iCountStop = m_CloneLinks.Count();
  624. if( iCountStop > listMax )
  625. iCountStop = listMax;
  626. for( int i = 0; i != iCountStop; ++i, ++pList )
  627. *pList = m_CloneLinks[i].pClone;
  628. return iCountStop;
  629. }
  630. void CPhysicsShadowClone::VPhysicsDestroyObject( void )
  631. {
  632. SetMoveType( MOVETYPE_NONE );
  633. SetSolid( SOLID_NONE );
  634. SetSolidFlags( 0 );
  635. SetCollisionGroup( COLLISION_GROUP_NONE );
  636. CollisionRulesChanged();
  637. VPhysicsSetObject( NULL );
  638. for( int i = m_CloneLinks.Count(); --i >= 0; )
  639. {
  640. Assert( m_CloneLinks[i].pClone != NULL );
  641. m_pOwnerPhysEnvironment->DestroyObject( m_CloneLinks[i].pClone );
  642. }
  643. m_CloneLinks.RemoveAll();
  644. BaseClass::VPhysicsDestroyObject();
  645. }
  646. bool CPhysicsShadowClone::ShouldCollide( int collisionGroup, int contentsMask ) const
  647. {
  648. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  649. if( pClonedEntity )
  650. return pClonedEntity->ShouldCollide( collisionGroup, contentsMask );
  651. else
  652. return false;
  653. }
  654. bool CPhysicsShadowClone::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& trace )
  655. {
  656. return false;
  657. /*CBaseEntity *pSourceEntity = m_hClonedEntity.Get();
  658. if( pSourceEntity == NULL )
  659. return false;
  660. enginetrace->ClipRayToEntity( ray, fContentsMask, pSourceEntity, &trace );
  661. return trace.DidHit();*/
  662. }
  663. int CPhysicsShadowClone::ObjectCaps( void )
  664. {
  665. return ((BaseClass::ObjectCaps() | FCAP_DONT_SAVE) & ~(FCAP_FORCE_TRANSITION | FCAP_ACROSS_TRANSITION | FCAP_MUST_SPAWN | FCAP_SAVE_NON_NETWORKABLE));
  666. }
  667. void CPhysicsShadowClone::SetCloneTransformationMatrix( const matrix3x4_t &sourceMatrix )
  668. {
  669. m_matrixShadowTransform.Init( sourceMatrix );
  670. m_bShadowTransformIsIdentity = m_matrixShadowTransform.IsIdentity();
  671. if( m_matrixShadowTransform.InverseGeneral( m_matrixShadowTransform_Inverse ) == false )
  672. {
  673. m_matrixShadowTransform.InverseTR( m_matrixShadowTransform_Inverse ); //probably not the right matrix, but we're out of options
  674. }
  675. FullSync();
  676. //PartialSync( true );
  677. }
  678. void CPhysicsShadowClone::SetClonedEntity( EHANDLE hEntToClone )
  679. {
  680. VPhysicsDestroyObject();
  681. m_hClonedEntity = hEntToClone;
  682. //FullSyncClonedPhysicsObjects();
  683. }
  684. EHANDLE CPhysicsShadowClone::GetClonedEntity( void )
  685. {
  686. return m_hClonedEntity;
  687. }
  688. //damage relays to source entity
  689. bool CPhysicsShadowClone::PassesDamageFilter( const CTakeDamageInfo &info )
  690. {
  691. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  692. if( pClonedEntity )
  693. return pClonedEntity->PassesDamageFilter( info );
  694. else
  695. return BaseClass::PassesDamageFilter( info );
  696. }
  697. bool CPhysicsShadowClone::CanBeHitByMeleeAttack( CBaseEntity *pAttacker )
  698. {
  699. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  700. if( pClonedEntity )
  701. return pClonedEntity->CanBeHitByMeleeAttack( pAttacker );
  702. else
  703. return BaseClass::CanBeHitByMeleeAttack( pAttacker );
  704. }
  705. int CPhysicsShadowClone::OnTakeDamage( const CTakeDamageInfo &info )
  706. {
  707. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  708. if( pClonedEntity )
  709. return pClonedEntity->OnTakeDamage( info );
  710. else
  711. return BaseClass::OnTakeDamage( info );
  712. }
  713. int CPhysicsShadowClone::TakeHealth( float flHealth, int bitsDamageType )
  714. {
  715. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  716. if( pClonedEntity )
  717. return pClonedEntity->TakeHealth( flHealth, bitsDamageType );
  718. else
  719. return BaseClass::TakeHealth( flHealth, bitsDamageType );
  720. }
  721. void CPhysicsShadowClone::Event_Killed( const CTakeDamageInfo &info )
  722. {
  723. CBaseEntity *pClonedEntity = m_hClonedEntity.Get();
  724. if( pClonedEntity )
  725. pClonedEntity->Event_Killed( info );
  726. else
  727. BaseClass::Event_Killed( info );
  728. }
  729. CPhysicsShadowClone *CPhysicsShadowClone::CreateShadowClone( IPhysicsEnvironment *pInPhysicsEnvironment, EHANDLE hEntToClone, const char *szDebugMarker, const matrix3x4_t *pTransformationMatrix /*= NULL*/ )
  730. {
  731. AssertMsg( szDebugMarker != NULL, "All shadow clones must have a debug marker for where it came from in debug builds." );
  732. if( !sv_use_shadow_clones.GetBool() )
  733. return NULL;
  734. CBaseEntity *pClonedEntity = hEntToClone.Get();
  735. if( pClonedEntity == NULL )
  736. return NULL;
  737. AssertMsg( IsShadowClone( pClonedEntity ) == false, "Shouldn't attempt to clone clones" );
  738. if( pClonedEntity->IsMarkedForDeletion() )
  739. return NULL;
  740. //if( pClonedEntity->IsPlayer() )
  741. // return NULL;
  742. IPhysicsObject *pPhysics = pClonedEntity->VPhysicsGetObject();
  743. if( pPhysics == NULL )
  744. return NULL;
  745. if( pClonedEntity->GetSolid() == SOLID_BSP )
  746. return NULL;
  747. if( pClonedEntity->GetSolidFlags() & (FSOLID_NOT_SOLID | FSOLID_TRIGGER) )
  748. return NULL;
  749. if( pClonedEntity->GetFlags() & (FL_WORLDBRUSH | FL_STATICPROP) )
  750. return NULL;
  751. /*if( FClassnameIs( pClonedEntity, "func_door" ) )
  752. {
  753. //only clone func_door's that are in front of the portal
  754. return NULL;
  755. }*/
  756. // Too many shadow clones breaks the game (too many entities)
  757. if( g_iShadowCloneCount >= MAX_SHADOW_CLONE_COUNT )
  758. {
  759. AssertMsg( false, "Too many shadow clones, consider upping the limit or reducing the level's physics props" );
  760. return NULL;
  761. }
  762. ++g_iShadowCloneCount;
  763. CPhysicsShadowClone *pClone = (CPhysicsShadowClone*)CreateEntityByName("physicsshadowclone");
  764. s_IsShadowClone[pClone->entindex()] = true;
  765. pClone->m_pOwnerPhysEnvironment = pInPhysicsEnvironment;
  766. pClone->m_hClonedEntity = hEntToClone;
  767. DBG_CODE_NOSCOPE( pClone->m_szDebugMarker = szDebugMarker; );
  768. CPhysicsShadowCloneLL *pCloneLLEntry = s_SCLLManager.Alloc();
  769. pCloneLLEntry->pClone = pClone;
  770. pCloneLLEntry->pNext = s_EntityClones[pClonedEntity->entindex()];
  771. s_EntityClones[pClonedEntity->entindex()] = pCloneLLEntry;
  772. if( pTransformationMatrix )
  773. {
  774. pClone->m_matrixShadowTransform.Init( *pTransformationMatrix );
  775. pClone->m_bShadowTransformIsIdentity = pClone->m_matrixShadowTransform.IsIdentity();
  776. if( !pClone->m_bShadowTransformIsIdentity )
  777. {
  778. if( pClone->m_matrixShadowTransform.InverseGeneral( pClone->m_matrixShadowTransform_Inverse ) == false )
  779. {
  780. pClone->m_matrixShadowTransform.InverseTR( pClone->m_matrixShadowTransform_Inverse ); //probably not the right matrix, but we're out of options
  781. }
  782. }
  783. }
  784. DispatchSpawn( pClone );
  785. return pClone;
  786. }
  787. void CPhysicsShadowClone::Free( void )
  788. {
  789. VPhysicsDestroyObject();
  790. UTIL_Remove( this );
  791. //Too many shadow clones breaks the game (too many entities)
  792. --g_iShadowCloneCount;
  793. }
  794. void CPhysicsShadowClone::FullSyncAllClones( void )
  795. {
  796. for( int i = s_ActiveShadowClones.Count(); --i >= 0; )
  797. {
  798. s_ActiveShadowClones[i]->FullSync( true );
  799. }
  800. }
  801. IPhysicsObject *CPhysicsShadowClone::TranslatePhysicsToClonedEnt( const IPhysicsObject *pPhysics )
  802. {
  803. if( m_hClonedEntity.Get() != NULL )
  804. {
  805. for( int i = m_CloneLinks.Count(); --i >= 0; )
  806. {
  807. if( m_CloneLinks[i].pClone == pPhysics )
  808. return m_CloneLinks[i].pSource;
  809. }
  810. }
  811. return NULL;
  812. }
  813. void CPhysicsShadowClone::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent )
  814. {
  815. //the baseclass just screenshakes, makes sounds, and outputs dust, we rely on the original entity to do this when applicable
  816. }
  817. bool CPhysicsShadowClone::IsShadowClone( const CBaseEntity *pEntity )
  818. {
  819. return s_IsShadowClone[pEntity->entindex()];
  820. }
  821. CPhysicsShadowCloneLL *CPhysicsShadowClone::GetClonesOfEntity( const CBaseEntity *pEntity )
  822. {
  823. return s_EntityClones[pEntity->entindex()];
  824. }
  825. void CPhysicsShadowClone::DestroyClonedPhys( IPhysicsObject *pPhys )
  826. {
  827. for( int i = m_CloneLinks.Count(); --i >= 0; )
  828. {
  829. if( pPhys == m_CloneLinks[i].pSource )
  830. {
  831. m_pOwnerPhysEnvironment->DestroyObject( m_CloneLinks[i].pClone ); //also destroys shadow controller
  832. m_CloneLinks.FastRemove( i );
  833. }
  834. }
  835. }
  836. void CPhysicsShadowClone::DestroyClonedCollideable( CPhysCollide *pCollide )
  837. {
  838. for( int i = m_CloneLinks.Count(); --i >= 0; )
  839. {
  840. if( pCollide == m_CloneLinks[i].pSource->GetCollide() )
  841. {
  842. m_pOwnerPhysEnvironment->DestroyObject( m_CloneLinks[i].pClone ); //also destroys shadow controller
  843. m_CloneLinks.FastRemove( i );
  844. }
  845. }
  846. }
  847. void CPhysicsShadowClone::NotifyDestroy( IPhysicsObject *pDestroyingPhys, CBaseEntity *pOwningEntity )
  848. {
  849. if( pOwningEntity )
  850. {
  851. CPhysicsShadowCloneLL *pCloneLL = GetClonesOfEntity( pOwningEntity );
  852. while( pCloneLL )
  853. {
  854. pCloneLL->pClone->DestroyClonedPhys( pDestroyingPhys );
  855. pCloneLL = pCloneLL->pNext;
  856. }
  857. }
  858. else
  859. {
  860. for( int i = 0; i != s_ActiveShadowClones.Count(); ++i )
  861. {
  862. s_ActiveShadowClones[i]->DestroyClonedPhys( pDestroyingPhys );
  863. }
  864. }
  865. }
  866. void CPhysicsShadowClone::NotifyDestroy( CPhysCollide *pDestroyingCollide, CBaseEntity *pOwningEntity )
  867. {
  868. if( pOwningEntity )
  869. {
  870. CPhysicsShadowCloneLL *pCloneLL = GetClonesOfEntity( pOwningEntity );
  871. while( pCloneLL )
  872. {
  873. pCloneLL->pClone->DestroyClonedCollideable( pDestroyingCollide );
  874. pCloneLL = pCloneLL->pNext;
  875. }
  876. }
  877. else
  878. {
  879. for( int i = 0; i != s_ActiveShadowClones.Count(); ++i )
  880. {
  881. s_ActiveShadowClones[i]->DestroyClonedCollideable( pDestroyingCollide );
  882. }
  883. }
  884. }
  885. void DrawDebugOverlayForShadowClone( CPhysicsShadowClone *pClone )
  886. {
  887. unsigned char iColorIntensity = (pClone->IsInAssumedSyncState())?(127):(255);
  888. int iRed = (pClone->IsUntransformedClone())?(0):(iColorIntensity);
  889. int iGreen = iColorIntensity;
  890. int iBlue = iColorIntensity;
  891. CPortalSimulator *pSimulator = CPortalSimulator::GetSimulatorThatOwnsEntity( pClone );
  892. if( pSimulator )
  893. {
  894. Color debugColor = pSimulator->GetInternalData().Debugging.overlayColor;
  895. iRed = debugColor.r();
  896. iGreen = debugColor.g();
  897. iBlue = debugColor.b();
  898. }
  899. for( int i = 0; i != pClone->m_CloneLinks.Count(); ++i )
  900. {
  901. IPhysicsObject *pPhys = pClone->m_CloneLinks[i].pClone;
  902. if( pPhys )
  903. {
  904. const CPhysCollide *pCollide = pPhys->GetCollide();
  905. if( pCollide )
  906. {
  907. Vector origin;
  908. QAngle angles;
  909. pPhys->GetPosition( &origin, &angles );
  910. Vector *outVerts;
  911. int vertCount = physcollision->CreateDebugMesh( pCollide, &outVerts );
  912. int triCount = vertCount / 3;
  913. int vert = 0;
  914. VMatrix tmp = SetupMatrixOrgAngles( origin, angles );
  915. int i;
  916. for ( i = 0; i < vertCount; i++ )
  917. {
  918. outVerts[i] = tmp.VMul4x3( outVerts[i] );
  919. }
  920. for ( i = 0; i < triCount; i++ )
  921. {
  922. NDebugOverlay::Line( outVerts[vert], outVerts[vert + 1], iRed, iGreen, iBlue, true, 0.0f );
  923. NDebugOverlay::Line( outVerts[vert + 1], outVerts[vert + 2], iRed, iGreen, iBlue, true, 0.0f );
  924. NDebugOverlay::Line( outVerts[vert + 2], outVerts[vert], iRed, iGreen, iBlue, true, 0.0f );
  925. vert += 3;
  926. }
  927. physcollision->DestroyDebugMesh( vertCount, outVerts );
  928. }
  929. }
  930. }
  931. NDebugOverlay::EntityBounds( pClone, iRed, iGreen, iBlue, (iColorIntensity>>2), 0.0f );
  932. }
  933. bool CTraceFilterTranslateClones::ShouldHitEntity( IHandleEntity *pEntity, int contentsMask )
  934. {
  935. CBaseEntity *pEnt = EntityFromEntityHandle( pEntity );
  936. if( CPhysicsShadowClone::IsShadowClone( pEnt ) )
  937. {
  938. CBaseEntity *pClonedEntity = ((CPhysicsShadowClone *)pEnt)->GetClonedEntity();
  939. CPortalSimulator *pSimulator = CPortalSimulator::GetSimulatorThatOwnsEntity( pEnt )->GetLinkedPortalSimulator();
  940. if( pSimulator->GetInternalData().Simulation.Dynamic.EntFlags[pClonedEntity->entindex()] & PSEF_IS_IN_PORTAL_HOLE )
  941. return m_pActualFilter->ShouldHitEntity( pClonedEntity, contentsMask );
  942. else
  943. return false;
  944. }
  945. else
  946. {
  947. return m_pActualFilter->ShouldHitEntity( pEntity, contentsMask );
  948. }
  949. }
  950. TraceType_t CTraceFilterTranslateClones::GetTraceType() const
  951. {
  952. return m_pActualFilter->GetTraceType();
  953. }