void CElementRPCs::AttachElements ( NetBitStreamInterface& bitStream ) { ElementID ID, usAttachedToID; CVector vecPosition, vecRotation; if ( bitStream.Read ( ID ) && bitStream.Read ( usAttachedToID ) && bitStream.Read ( vecPosition.fX ) && bitStream.Read ( vecPosition.fY ) && bitStream.Read ( vecPosition.fZ ) && bitStream.Read ( vecRotation.fX ) && bitStream.Read ( vecRotation.fY ) && bitStream.Read ( vecRotation.fZ ) ) { CClientEntity* pEntity = CElementIDs::GetElement ( ID ); CClientEntity* pAttachedToEntity = CElementIDs::GetElement ( usAttachedToID ); if ( pEntity && pAttachedToEntity ) { pEntity->SetAttachedOffsets ( vecPosition, vecRotation ); pEntity->AttachTo ( pAttachedToEntity ); } } }
void CElementRPCs::DetachElements ( NetBitStreamInterface& bitStream ) { ElementID ID; unsigned char ucTimeContext; if ( bitStream.Read ( ID ) && bitStream.Read ( ucTimeContext ) ) { CClientEntity* pEntity = CElementIDs::GetElement ( ID ); if ( pEntity ) { pEntity->SetSyncTimeContext ( ucTimeContext ); pEntity->AttachTo ( NULL ); CVector vecPosition; if ( bitStream.Read ( vecPosition.fX ) && bitStream.Read ( vecPosition.fY ) && bitStream.Read ( vecPosition.fZ ) ) { pEntity->SetPosition ( vecPosition ); } } } }
CClientEntity::~CClientEntity ( void ) { // Make sure we won't get deleted later by the element deleter if we've been requested so if ( m_bBeingDeleted ) { g_pClientGame->GetElementDeleter ()->Unreference ( this ); } // Remove from parent ClearChildren (); SetParent ( NULL ); // Reset our index in the element array if ( m_ID != INVALID_ELEMENT_ID ) { CElementIDs::SetElement ( m_ID, NULL ); // Got a clientside ID? Push it back on our stack so we don't run out of client id's if ( IsLocalEntity () ) { CElementIDs::PushClientID ( m_ID ); } } // Remove our custom data if ( m_pCustomData ) { delete m_pCustomData; } // Detach from everything AttachTo( NULL ); while( m_AttachedEntities.size() ) { CClientEntity* pAttachedEntity = m_AttachedEntities.back(); pAttachedEntity->AttachTo( NULL ); } m_bDisallowAttaching = true; assert( !m_pAttachedToEntity && m_AttachedEntities.empty() ); RemoveAllCollisions (); if ( m_pEventManager ) { delete m_pEventManager; m_pEventManager = NULL; } if ( m_pElementGroup ) { m_pElementGroup->Remove ( this ); } if ( m_OriginSourceUsers.size () > 0 ) { list < CClientPed* > ::iterator iterUsers = m_OriginSourceUsers.begin (); for ( ; iterUsers != m_OriginSourceUsers.end () ; iterUsers++ ) { CClientPed* pModel = *iterUsers; if ( pModel->m_interp.pTargetOriginSource == this ) { pModel->m_interp.pTargetOriginSource = NULL; pModel->m_interp.bHadOriginSource = true; } } m_OriginSourceUsers.clear (); } // Unlink our contacts list < CClientPed * > ::iterator iterContacts = m_Contacts.begin (); for ( ; iterContacts != m_Contacts.end () ; iterContacts++ ) { CClientPed * pModel = *iterContacts; if ( pModel->GetCurrentContactEntity () == this ) { pModel->SetCurrentContactEntity ( NULL ); } } m_Contacts.clear (); // Unlink disabled-collisions while ( !m_DisabledCollisions.empty () ) { CClientEntity * pEntity = m_DisabledCollisions.begin ()->first; SetCollidableWith ( pEntity, true ); } // Remove from spatial database if ( !g_pClientGame->IsBeingDeleted () ) GetClientSpatialDatabase ()->RemoveEntity ( this ); // Ensure not referenced in the disabled collisions list assert ( !MapContains ( g_pClientGame->m_AllDisabledCollisions, this ) ); // Ensure nothing has inadvertently set a parent assert ( m_pParent == NULL ); if ( !g_pClientGame->IsBeingDeleted () ) CClientEntityRefManager::OnEntityDelete ( this ); g_pClientGame->GetGameEntityXRefManager ()->OnClientEntityDelete ( this ); SAFE_RELEASE( m_pChildrenListSnapshot ); g_pCore->GetGraphics ()->GetRenderItemManager ()->RemoveClientEntityRefs ( this ); g_pCore->UpdateDummyProgress(); }