int CPortalGameMovement::CheckStuck( void ) { if( BaseClass::CheckStuck() ) { CPortal_Player *pPortalPlayer = GetPortalPlayer(); #ifndef CLIENT_DLL if( pPortalPlayer->IsAlive() ) g_PortalGameStats.Event_PlayerStuck( pPortalPlayer ); #endif //try to fix it, then recheck Vector vIndecisive; if( pPortalPlayer->m_hPortalEnvironment ) { pPortalPlayer->m_hPortalEnvironment->GetVectors( &vIndecisive, NULL, NULL ); } else { vIndecisive.Init( 0.0f, 0.0f, 1.0f ); } Vector ptOldOrigin = pPortalPlayer->GetAbsOrigin(); if( pPortalPlayer->m_hPortalEnvironment ) { if( !FindClosestPassableSpace( pPortalPlayer, vIndecisive ) ) { #ifndef CLIENT_DLL DevMsg( "Hurting the player for FindClosestPassableSpaceFailure!" ); CTakeDamageInfo info( pPortalPlayer, pPortalPlayer, vec3_origin, vec3_origin, 1e10, DMG_CRUSH ); pPortalPlayer->OnTakeDamage( info ); #endif } //make sure we didn't get put behind the portal >_< Vector ptCurrentOrigin = pPortalPlayer->GetAbsOrigin(); if( vIndecisive.Dot( ptCurrentOrigin - ptOldOrigin ) < 0.0f ) { pPortalPlayer->SetAbsOrigin( ptOldOrigin + (vIndecisive * 5.0f) ); //this is an anti-bug hack, since this would have probably popped them out of the world, we're just going to move them forward a few units } } mv->SetAbsOrigin( pPortalPlayer->GetAbsOrigin() ); return BaseClass::CheckStuck(); } else { return 0; } }
void CPortalGameMovement::FunnelIntoPortal( CProp_Portal *pPortal, Vector &wishdir ) { // Make sure there's a portal if ( !pPortal ) return; // Get portal vectors Vector vPortalForward, vPortalRight, vPortalUp; pPortal->GetVectors( &vPortalForward, &vPortalRight, &vPortalUp ); // Make sure it's a floor portal if ( vPortalForward.z < 0.8f ) return; vPortalRight.z = 0.0f; vPortalUp.z = 0.0f; VectorNormalize( vPortalRight ); VectorNormalize( vPortalUp ); // Make sure the player is looking downward CPortal_Player *pPlayer = GetPortalPlayer(); Vector vPlayerForward; pPlayer->EyeVectors( &vPlayerForward ); if ( vPlayerForward.z > -0.1f ) return; Vector vPlayerOrigin = pPlayer->GetAbsOrigin(); Vector vPlayerToPortal = pPortal->GetAbsOrigin() - vPlayerOrigin; // Make sure the player is trying to air control, they're falling downward and they are vertically close to the portal if ( fabsf( wishdir[ 0 ] ) > 64.0f || fabsf( wishdir[ 1 ] ) > 64.0f || mv->m_vecVelocity[ 2 ] > -165.0f || vPlayerToPortal.z < -512.0f ) return; // Make sure we're in the 2D portal rectangle if ( ( vPlayerToPortal.Dot( vPortalRight ) * vPortalRight ).Length() > PORTAL_HALF_WIDTH * 1.5f ) return; if ( ( vPlayerToPortal.Dot( vPortalUp ) * vPortalUp ).Length() > PORTAL_HALF_HEIGHT * 1.5f ) return; if ( vPlayerToPortal.z > -8.0f ) { // We're too close the the portal to continue correcting, but zero the velocity so our fling velocity is nice mv->m_vecVelocity[ 0 ] = 0.0f; mv->m_vecVelocity[ 1 ] = 0.0f; } else { // Funnel toward the portal float fFunnelX = vPlayerToPortal.x * PORTAL_FUNNEL_AMOUNT - mv->m_vecVelocity[ 0 ]; float fFunnelY = vPlayerToPortal.y * PORTAL_FUNNEL_AMOUNT - mv->m_vecVelocity[ 1 ]; wishdir[ 0 ] += fFunnelX; wishdir[ 1 ] += fFunnelY; } }