// // Handle the changing state of collision between one entity and any colshape // void CColManager::DoHitDetectionForEntity ( const CVector& vecNowPosition, CElement* pEntity ) { std::map < CColShape*, int > shortList; // Get all entities within the sphere CElementResult queryResult; GetSpatialDatabase()->SphereQuery ( queryResult, CSphere ( vecNowPosition, 0.0f ) ); // Extract colshapes for ( CElementResult ::const_iterator it = queryResult.begin () ; it != queryResult.end (); ++it ) if ( (*it)->GetType () == CElement::COLSHAPE ) shortList[ (CColShape*)*it ] = 1; // Add existing collisions, so they can be disconnected if required for ( list < CColShape* > ::const_iterator it = pEntity->CollisionsBegin () ; it != pEntity->CollisionsEnd (); ++it ) shortList[ *it ] = 1; // Test each colshape against the entity for ( std::map < CColShape*, int > ::const_iterator it = shortList.begin () ; it != shortList.end (); ++it ) { CColShape* pShape = it->first; // Enabled and not being deleted? if ( !pShape->IsBeingDeleted () && pShape->IsEnabled () ) { // Collided? bool bHit = pShape->DoHitDetection ( vecNowPosition ); HandleHitDetectionResult ( bHit, pShape, pEntity ); } } }
// // Handle the changing state of collision between one colshape and any entity // void CColManager::DoHitDetectionForColShape ( CColShape* pShape ) { // Ensure colshape is enabled and not being deleted if ( pShape->IsBeingDeleted () || !pShape->IsEnabled () ) return; std::map < CElement*, int > entityList; // Get all entities within the sphere CSphere querySphere = pShape->GetWorldBoundingSphere (); CElementResult result; GetSpatialDatabase()->SphereQuery ( result, querySphere ); // Extract relevant types for ( CElementResult::const_iterator it = result.begin () ; it != result.end (); ++it ) { CElement* pEntity = *it; switch ( pEntity->GetType () ) { case CElement::COLSHAPE: case CElement::SCRIPTFILE: case CElement::RADAR_AREA: case CElement::CONSOLE: case CElement::TEAM: case CElement::BLIP: case CElement::DUMMY: break; default: if ( pEntity->GetParentEntity () ) entityList[ pEntity ] = 1; } } // Add existing colliders, so they can be disconnected if required for ( list < CElement* > ::const_iterator it = pShape->CollidersBegin () ; it != pShape->CollidersEnd (); ++it ) { entityList[ *it ] = 1; } // Test each entity against the colshape for ( std::map < CElement*, int > ::const_iterator it = entityList.begin () ; it != entityList.end (); ++it ) { CElement* pEntity = it->first; CVector vecPosition = pEntity->GetPosition (); // Collided? bool bHit = pShape->DoHitDetection ( vecPosition ); HandleHitDetectionResult ( bHit, pShape, pEntity ); } }
// Put this player in other players nearlist if this player can observe them in some way void CPlayer::UpdateOthersNearList ( void ) { m_UpdateNearListTimer.Reset (); // Get the two positions to check const CVector& vecPlayerPosition = GetPosition (); CVector vecCameraPosition; GetCamera ()->GetPosition ( vecCameraPosition ); m_vecUpdateNearLastPosition = vecPlayerPosition; // Fill resultNearBoth with rough list of nearby players CElementResult resultNearBoth; { // Calculate distance from player to his camera. (Note as spatial database is 2D, we can use the 2D distance here) const float fCameraDistance = DistanceBetweenPoints2D ( vecCameraPosition, vecPlayerPosition ); if ( fCameraDistance < 40.f ) { // // If player near his camera (which is the usual case), we can do optimized things // // Do one query with a slightly bigger sphere const CVector vecAvgPos = ( vecCameraPosition + vecPlayerPosition ) * 0.5f; GetSpatialDatabase()->SphereQuery ( resultNearBoth, CSphere ( vecAvgPos, DISTANCE_FOR_NEAR_VIEWER + fCameraDistance * 0.5f ) ); } else { // // Bit more complicated if camera is not near player // // Perform queries on spatial database CElementResult resultNearCamera; GetSpatialDatabase()->SphereQuery ( resultNearCamera, CSphere ( vecCameraPosition, DISTANCE_FOR_NEAR_VIEWER ) ); CElementResult resultNearPlayer; GetSpatialDatabase()->SphereQuery ( resultNearPlayer, CSphere ( vecPlayerPosition, DISTANCE_FOR_NEAR_VIEWER ) ); std::set < CPlayer* > mergedList; // Merge for ( CElementResult::const_iterator it = resultNearCamera.begin () ; it != resultNearCamera.end (); ++it ) if ( (*it)->GetType () == CElement::PLAYER ) mergedList.insert ( (CPlayer*)*it ); for ( CElementResult::const_iterator it = resultNearPlayer.begin () ; it != resultNearPlayer.end (); ++it ) if ( (*it)->GetType () == CElement::PLAYER ) mergedList.insert ( (CPlayer*)*it ); // Copy to resultNearBoth for ( std::set < CPlayer* > ::iterator it = mergedList.begin (); it != mergedList.end (); ++it ) resultNearBoth.push_back ( *it ); } } // Accurately check distance to other players, and put this player in their near list for ( CElementResult::const_iterator it = resultNearBoth.begin () ; it != resultNearBoth.end (); ++it ) { if ( (*it)->GetType () == CElement::PLAYER ) { CPlayer* pOtherPlayer = (CPlayer*)*it; if ( pOtherPlayer != this ) { const CVector& vecOtherPlayerPos = pOtherPlayer->GetPosition (); // Check distance is accurate if ( ( vecPlayerPosition - vecOtherPlayerPos ).LengthSquared () < DISTANCE_FOR_NEAR_VIEWER * DISTANCE_FOR_NEAR_VIEWER || ( vecCameraPosition - vecOtherPlayerPos ).LengthSquared () < DISTANCE_FOR_NEAR_VIEWER * DISTANCE_FOR_NEAR_VIEWER ) { // Check dimension matches if ( m_usDimension == pOtherPlayer->GetDimension () ) { pOtherPlayer->RefreshNearPlayer ( this ); // Lightsync needs it the other way round if ( g_pBandwidthSettings->bLightSyncEnabled ) this->RefreshNearPlayer ( pOtherPlayer ); } } } } } }