i got working physics implementation, but i need to reimplement that using 30fps emulation, So remove "float dt", make own timer for 30fps emulation, use gravity as 0.008f (per frame). Here code: void Player::Update(float deltaTime)
{
    float timestep = CTimer::GetTimeStep();

    // Handle state-specific behavior
    switch (m_state)
    {
    case PlayerState::STANDING:
        HandleStanding(timestep);
        break;
    case PlayerState::JUMPING:
        HandleJumping(timestep);
        break;
    case PlayerState::FALLING:
        HandleFalling(timestep);
        break;
    case PlayerState::LANDING:
        HandleLanding(timestep);
        break;
    default:
        break;
    }

    // Check if player should be falling
    if (isPlayerInAir() && m_state != PlayerState::JUMPING && m_state != PlayerState::FALLING)
    {
        SetState(PlayerState::FALLING);
        std::cout << "Transitioning to FALLING state in Update." << std::endl;
    }

    // Apply physics when in air
    if (isPlayerInAir())
    {
        ApplyGravity(timestep);
        ApplyAirResistance(timestep);
        HandleAirCollisions(timestep);
    }

    // Update position
    UpdatePosition(timestep);
}

bool Player::isPlayerInAir()
{
    glm::vec3 raycastOrigin = GetPosition() + glm::vec3(0.0f, 0.05f, 0.0f);
    glm::vec3 downDirection(0.0f, -1.0f, 0.0f);

    auto fallResult = m_world->PlayerBoxRaycast(raycastOrigin, downDirection,
        1000.0f, m_playerDimensions, GetRotation());

    return !fallResult.hit || fallResult.distance > m_groundThreshold;
}

void Player::HandleAirCollisions(float timestep)
{
    const int numRayChecks = 3;
    float heightIntervals[] = { 0.2f, 0.5f, 0.8f }; // Check bottom, middle, and top

    // Get forward movement direction
    glm::vec3 forwardDir = glm::normalize(glm::vec3(m_moveSpeed.x, 0.0f, m_moveSpeed.z));
    if (glm::length2(forwardDir) < 0.001f) return;

    float collisionDistance = m_playerDimensions.x * 0.5f;

    // Check collisions at different heights
    for (int i = 0; i < numRayChecks; i++)
    {
        glm::vec3 rayOrigin = GetPosition() +
            glm::vec3(0.0f, m_playerDimensions.y * heightIntervals[i], 0.0f);

        auto collisionResult = m_world->PlayerBoxRaycast(rayOrigin, forwardDir,
            collisionDistance, m_playerDimensions, GetRotation());

        if (collisionResult.hit && collisionResult.distance <= collisionDistance)
        {
            std::cout << "Collision detected at height " << heightIntervals[i] << std::endl;

            // Stop horizontal movement
            m_moveSpeed.x = 0.0f;
            m_moveSpeed.z = 0.0f;

            // Calculate push-back distance
            float pushBackDist = collisionDistance - collisionResult.distance + 0.01f;

            // Apply push-back
            glm::vec3 currentPos = GetPosition();
            glm::vec3 pushBack = -forwardDir * pushBackDist;
            pushBack.y = 0.0f;

            SetPosition(currentPos + pushBack);
            return; // Exit after handling first collision
        }
    }
}

void Player::UpdatePosition(float timestep)
{
    glm::vec3 proposedMove = m_moveSpeed * timestep;
    glm::vec3 newPosition = GetPosition();

    // Apply horizontal movement
    newPosition.x += proposedMove.x;
    newPosition.z += proposedMove.z;

    // Check for horizontal collision at new position
    glm::vec3 moveDir = glm::normalize(glm::vec3(proposedMove.x, 0.0f, proposedMove.z));
    if (glm::length2(moveDir) > 0.001f)
    {
        glm::vec3 checkPos = newPosition + glm::vec3(0.0f, m_playerDimensions.y * 0.5f, 0.0f);
        auto collisionCheck = m_world->PlayerBoxRaycast(checkPos, moveDir,
            m_playerDimensions.x * 0.5f, m_playerDimensions, GetRotation());

        if (collisionCheck.hit)
        {
            // Revert to previous horizontal position
            newPosition.x = GetPosition().x;
            newPosition.z = GetPosition().z;
        }
    }

    // Apply vertical movement
    newPosition.y += proposedMove.y;

    SetPosition(newPosition);
    m_MoveSpeedPerTick = GetPosition() - m_PreviousPosition;
    m_PreviousPosition = GetPosition();
}

glm::vec3 Player::GetGroundPos()
{
    glm::vec3 playerPosition = GetPosition();
    glm::quat playerRotation = GetRotation();

    glm::vec3 downDirection(0.0f, -1.0f, 0.0f);
    float maxFallDistance = 1000.0f;
    glm::vec3 raycastOrigin = playerPosition + glm::vec3(0.0f, m_groundThreshold, 0.0f);
    auto fallResult = m_world->PlayerBoxRaycast(raycastOrigin, downDirection,
        maxFallDistance, m_playerDimensions, playerRotation);

    if (fallResult.hit)
    {
        return fallResult.hitPoint;
    }
    return { 9999.0f, 9999.0f, 9999.0f };
}

void Player::ApplyGravity(float dt)
{
    m_moveSpeed.y -= 9.81f * dt;
    //m_moveSpeed.y -= 9.81 * 2.0f * CTimer::GetTimeStep();
}

void Player::ApplyAirResistance(float dt)
{
    if (m_fAirResistance > 0.1f) {
        float f = powf(m_fAirResistance, CTimer::GetTimeStep());
        m_moveSpeed *= f;
    }
    else {
        float magnitudeSqr = glm::length2(m_moveSpeed);
        float f = powf(1.0f / abs(m_fAirResistance * 0.5f * magnitudeSqr + 1.0f), CTimer::GetTimeStep());
        m_moveSpeed *= f;
    }
}

void Player::ApplyMoveForce(glm::vec3 force)
{
    m_moveSpeed += force * (1.0f / 70.0f);
}

void Player::Jump()
{
    if (m_state != PlayerState::STANDING && m_state != PlayerState::LANDING)
        return;

    SetState(PlayerState::JUMPING);
    std::cout << "Player started jumping." << std::endl;

    // Jump parameters
    const float maxHeight = 1.0f;
    const float jumpDistance = 4.5f;
    const float g = 9.81f;

    // Calculate velocities
    float v0y = std::sqrt(2.0f * g * maxHeight);
    float t_total = (2.0f * v0y) / g;
    float v0z = jumpDistance / t_total;

    // Get forward direction
    glm::vec3 forwardDir = GetRotation() * glm::vec3(0.0f, 0.0f, 1.0f);
    forwardDir = glm::normalize(glm::vec3(forwardDir.x, 0.0f, forwardDir.z));

    // Set velocities
    m_moveSpeed = glm::vec3(
        forwardDir.x * v0z,
        v0y,
        forwardDir.z * v0z
    );
}



void Player::HandleStanding(float dt)
{

}

void Player::HandleFalling(float dt)
{
    glm::vec3 groundPos = GetGroundPos();
    float dist = glm::distance(groundPos, GetPosition());

    if (dist >= 2000.0f)
    {
        std::cout << "Player is below the map! Resetting position." << std::endl;
        m_moveSpeed = glm::vec3(0.0f);
        SetPosition({ -15.3375f, 17.5399f, 69.3102f }); // Reset position
        return;
    }

    if (dist <= m_groundThreshold)
    {
        m_moveSpeed = glm::vec3(0.0f);
        // Only adjust Y position to ground level
        glm::vec3 newPos = GetPosition();
        newPos.y = groundPos.y;
        SetPosition(newPos);

        SetState(PlayerState::LANDING);
        std::cout << "Player has landed." << std::endl;
    }
}

void Player::HandleJumping(float dt)
{
    // Check if the player has reached the peak of the jump
    if (m_moveSpeed.y <= 0.0f)
    {
        // Transition to FALLING state
        SetState(PlayerState::FALLING);
        std::cout << "Player is now falling." << std::endl;
    }
}

void Player::HandleLanding(float dt)
{
    SetState(PlayerState::STANDING);
    std::cout << "Player is now standing." << std::endl;
}