Exemplo n.º 1
0
//
// 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 );
        }
    }
}
Exemplo n.º 2
0
//
// 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 );
    }
}
Exemplo n.º 3
0
void CElement::UpdateSpatialData ( void )
{
    // Avoid recursion
    if ( !m_bUpdatingSpatialData )
    {
        m_bUpdatingSpatialData = true;
        GetSpatialDatabase ()->UpdateEntity ( this );
        // Also make sure attached entites get updated
        for ( list < CElement * > ::iterator iter = m_AttachedElements.begin (); iter != m_AttachedElements.end () ; iter++ )
        {
            CElement* pElement = *iter;
            if ( pElement->GetAttachedToElement () )
            {
                CVector vecPosition;
                pElement->GetAttachedPosition ( vecPosition );
                pElement->SetPosition ( vecPosition );
            }
        }
        m_bUpdatingSpatialData = false;
    }
}
Exemplo n.º 4
0
CElement::~CElement ( void )
{
    // Get rid of the children elements
    ClearChildren ();
    SetParentObject ( NULL );

    // Remove ourselves from our element group
    if ( m_pElementGroup )
        m_pElementGroup->Remove ( this );

    // Delete our event manager
    delete m_pCustomData;
    delete m_pEventManager;

    // Unreference us from what's referencing us
    list < CPerPlayerEntity* > ::const_iterator iter = m_ElementReferenced.begin ();
    for ( ; iter != m_ElementReferenced.end (); iter++ )
    {
        (*iter)->m_ElementReferences.remove ( this );
    }

    RemoveAllCollisions ( true );

    // Null all camera elements referencing us
    std::list < CPlayerCamera* > cloneFollowingCameras = m_FollowingCameras;
    for ( std::list < CPlayerCamera* > ::const_iterator iter = cloneFollowingCameras.begin () ; iter != cloneFollowingCameras.end () ; iter++ )
    {
        (*iter)->SetTarget ( NULL );
    }

    if ( m_pAttachedTo )
        m_pAttachedTo->RemoveAttachedElement ( this );

    list < CElement* > ::iterator iterAttached = m_AttachedElements.begin ();
    for ( ; iterAttached != m_AttachedElements.end () ; iterAttached++ )
    {
        // Make sure our attached element stores it's current position
        (*iterAttached)->GetPosition ();
        // Unlink it
        (*iterAttached)->m_pAttachedTo = NULL;
    }

    list < CPed * > ::iterator iterUsers = m_OriginSourceUsers.begin ();
    for ( ; iterUsers != m_OriginSourceUsers.end () ; iterUsers++ )
    {
        CPed* pPed = *iterUsers;
        if ( pPed->m_pContactElement == this )
            pPed->m_pContactElement = NULL;
    }

    // Remove from spatial database
    GetSpatialDatabase ()->RemoveEntity ( this );

    if ( GetID() != INVALID_ELEMENT_ID && GetID() >= MAX_SERVER_ELEMENTS )
        CLogger::ErrorPrintf( "ERROR: Element ID is incorrect (%08x) (Type:%d)\n", GetID().Value(), GetType() );

    // Deallocate our unique ID
    CElementIDs::PushUniqueID ( this );

    // Remove our reference from the element deleter
    g_pGame->GetElementDeleter ()->Unreference ( this );

    // Ensure nothing has inadvertently set a parent
    assert ( m_pParent == NULL );

    CElementRefManager::OnElementDelete ( this );
    SAFE_RELEASE( m_pChildrenListSnapshot );
}
Exemplo n.º 5
0
// 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 );
                    }
                }
            }
        }
    }
}