i want you to make an time to any surface calculation inspired by this exsrapolation logic but instead of it being the ball its the player and the time to the different surfaces and then output the time to the surface that is the least time, SIDE_WALL_X = 4096.0f,
BACK_WALL_Y = 5120.0f,
CEILING_Z = 2044.0f,
FLOOR_Z = 17.0f,     // Actual floor height for cars
GRAVITY_Z = -650.0f, // Modify InitializeCarState to return hasFlipX as a std::pair
std::pair<CarState, bool> InitializeCarState(RocketSim::Car* rocketSimPlayer, const rlbot::flat::PlayerInfo* playerInfo, const RLGSC::Action& controls) {
    CarState carState = {};
    bool hasFlipX = false;  // Initialize hasFlipX

    if (rocketSimPlayer != nullptr) {
        const auto& rocketSimState = rocketSimPlayer->GetState();

        carState.updateCounter = rocketSimState.updateCounter;
        carState.isOnGround = rocketSimState.isOnGround;
        memcpy(carState.wheelsWithContact, rocketSimState.wheelsWithContact, sizeof(carState.wheelsWithContact));
        carState.hasJumped = rocketSimState.hasJumped;
        carState.hasDoubleJumped = rocketSimState.hasDoubleJumped;
        carState.hasFlipped = rocketSimState.hasFlipped;
        carState.flipRelTorque = rocketSimState.flipRelTorque;
        carState.flipTime = rocketSimState.flipTime;
        carState.isFlipping = rocketSimState.isFlipping;
        carState.isJumping = rocketSimState.isJumping;
        carState.jumpTime = carState.isOnGround ? 0 : rocketSimState.jumpTime;
        carState.airTime = rocketSimState.airTime;
        carState.airTimeSinceJump = rocketSimState.airTimeSinceJump;
        carState.boost = playerInfo->boost();
        carState.timeSpentBoosting = rocketSimState.timeSpentBoosting;
        carState.isSupersonic = rocketSimState.isSupersonic;
        carState.supersonicTime = rocketSimState.supersonicTime;
        carState.handbrakeVal = rocketSimState.handbrakeVal;
        carState.isAutoFlipping = rocketSimState.isAutoFlipping;
        carState.autoFlipTimer = rocketSimState.autoFlipTimer;
        carState.autoFlipTorqueScale = rocketSimState.autoFlipTorqueScale;
        carState.worldContact = rocketSimState.worldContact;
        carState.carContact = rocketSimState.carContact;
        carState.isDemoed = playerInfo->isDemolished();
        carState.demoRespawnTimer = rocketSimState.demoRespawnTimer;
        carState.ballHitInfo = rocketSimState.ballHitInfo;
        carState.lastControls = rocketSimState.lastControls;

        hasFlipX =
            !carState.hasDoubleJumped && !carState.hasFlipped
            && carState.airTimeSinceJump < RLConst::DOUBLEJUMP_MAX_DELAY;
    }
    else {
        // Fallback to using playerInfo for some fields
        carState.hasJumped = playerInfo->jumped();
        carState.hasDoubleJumped = playerInfo->doubleJumped();
        carState.isDemoed = playerInfo->isDemolished();
        carState.boost = playerInfo->boost();
    }

    return { carState, hasFlipX };  // Return both carState and hasFlipX
}

// Update ToPlayer to accept hasFlipX
PlayerData ToPlayer(const rlbot::flat::PlayerInfo* playerInfo, RocketSim::Car* rocketSimPlayer, uint64_t ticks, int tickSkip, const rlbot::GameTickPacket& gameTickPacket, const RLGSC::Action& controls) {
    PlayerData pd = {};
    pd.carId = playerInfo->spawnId();
    pd.team = (Team)playerInfo->team();
    pd.phys = ToPhysObj(playerInfo->physics());
    pd.physInv = pd.phys.Invert();
    pd.boostFraction = playerInfo->boost() / 100.f;

    // Initialize new fields
    pd.matchGoals = playerInfo->scoreInfo()->goals();
    pd.matchSaves = playerInfo->scoreInfo()->saves();
    pd.matchAssists = playerInfo->scoreInfo()->assists();
    pd.matchShots = playerInfo->scoreInfo()->shots();
    pd.matchShotPasses = 0; // This information might not be available from rlbot
    pd.matchBumps = 0; // This information might not be available from rlbot
    pd.matchDemos = 0; // This information might not be available from rlbot
    pd.boostPickups = 0; // This information might not be available from rlbot

    // Initialize CarState and retrieve hasFlipX
    auto [carState, hasFlipX] = InitializeCarState(rocketSimPlayer, playerInfo, controls);
    pd.carState = carState;

    pd.hasFlip = hasFlipX;

    pd.hasJump = !carState.hasJumped;

    // Initialize ball_touched to false
    pd.ballTouchedStep = false;
    pd.ballTouchedTick = false;

    return pd;
}


GameState ToGameState(rlbot::GameTickPacket& gameTickPacket, int ticksElapsed, int tickSkip, const std::vector<RocketSim::Car*>& rocketSimCars, uint64_t tickCount, const RLGSC::Action& controls) {
    GameState gs = {};

    const rlbot::flat::Touch* latestTouch = gameTickPacket->ball()->latestTouch();
    float currentTime = gameTickPacket->gameInfo()->secondsElapsed();

    auto players = gameTickPacket->players();
    for (int i = 0; i < players->size(); i++) {
        RocketSim::Car* rocketSimCar = (i < rocketSimCars.size()) ? rocketSimCars[i] : nullptr;
        PlayerData player = ToPlayer(players->Get(i), rocketSimCar, tickCount, tickSkip, gameTickPacket, controls);

        if (latestTouch != nullptr &&
            latestTouch->gameSeconds() > 0 &&
            i == latestTouch->playerIndex() &&
            currentTime - latestTouch->gameSeconds() < tickSkip / 120.0f) {
            player.ballTouchedStep = true;
        }
        else {
            player.ballTouchedStep = false;
        }

        gs.players.push_back(player);
    }

    gs.ball = ToPhysObj(gameTickPacket->ball()->physics());
    gs.ballInv = gs.ball.Invert();

    auto boostPadStates = gameTickPacket->boostPadStates();
    if (boostPadStates->size() != CommonValues::BOOST_LOCATIONS_AMOUNT) {
        if (rand() % 20 == 0) {
            RG_LOG(
                "RLBotClient ToGameState(): Bad boost pad amount, expected " << CommonValues::BOOST_LOCATIONS_AMOUNT << " but got " << boostPadStates->size()
            );
        }
        std::fill(gs.boostPads.begin(), gs.boostPads.end(), 1);
    }
    else {
        for (int i = 0; i < CommonValues::BOOST_LOCATIONS_AMOUNT; i++) {
            gs.boostPads[i] = boostPadStates->Get(i)->isActive();
            gs.boostPadsInv[CommonValues::BOOST_LOCATIONS_AMOUNT - i - 1] = gs.boostPads[i];
            gs.boostPadTimers[i] = boostPadStates->Get(i)->timer();
            gs.boostPadTimersInv[CommonValues::BOOST_LOCATIONS_AMOUNT - i - 1] = gs.boostPadTimers[i];
        }
    }

    return gs;
} here is the inspos float goalY = RLConst::SOCCAR_GOAL_SCORE_BASE_THRESHOLD_Y * (player.team == Team::BLUE ? 1 : -1);
float distToGoalY = std::abs(ball.pos.y - goalY);
float extrapScoreTime = distToGoalY / std::max(std::abs(ball.vel.y), 0.01f);
Vec extrapScorePos = ball.pos + ball.vel * extrapScoreTime;
extrapScorePos.z += CommonValues::GRAVITY_Z * (extrapScoreTime * extrapScoreTime) / 2;

if (extrapScoreTime <= MIN_SCORE_TIME || extrapScorePos.z >= MAX_EXTRAP_Z) {
				reward = 0.0f; // Disable reward if the ball is about to score or go too high
} // Define goal dimensions
float GOAL_WIDTH = 892.755f;
float GOAL_HEIGHT = 642.775f;
float goalY = RLConst::SOCCAR_GOAL_SCORE_BASE_THRESHOLD_Y * (player.team == Team::BLUE ? 1 : -1);
goalY *= 1.05f;

float distToScoring = abs(state.ball.pos.y - goalY);
float timeToScoring = distToScoring / (abs(state.ball.vel.y) + 1e-6);

Vec gravityDrop = Vec(0, 0, RLConst::GRAVITY_Z) * powf(timeToScoring, 2) * 0.5f;
Vec extrapBallPos = state.ball.pos + state.ball.vel * timeToScoring + gravityDrop;
extrapBallPos.z = RS_MAX(extrapBallPos.z, CommonValues::BALL_RADIUS);
//RG_LOG(extrapBallPos);

Vec targetPos = {
  RS_CLAMP(extrapBallPos.x, -GOAL_WIDTH, GOAL_WIDTH),
  goalY,
  RS_CLAMP(extrapBallPos.z, 0, GOAL_HEIGHT)
};