Lemon Collector
Key Required

Lemon Collector

Sell Lemons 🍋YAREKKKYAREKKK 1.1K views 4K executesUpdated Sep 27, 2026
Unrated
00
Lua Script•1520 lines (28076 chars)
--By YAREK
--Switch to First person and tap Y to start/stop farm
 
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer

if getgenv then
    local old = getgenv().LemonTreeScript

    if old then
        old.Running = false
        old.AutoCollecting = false

        if old.InputConnection then
            old.InputConnection:Disconnect()
        end

        if old.DescendantConnection then
            old.DescendantConnection:Disconnect()
        end

        if old.DescendantRemovingConnection then
            old.DescendantRemovingConnection:Disconnect()
        end

        if old.FlightConnection then
            old.FlightConnection:Disconnect()
        end

        if old.RescanConnection then
            old.RescanConnection:Disconnect()
        end

        if old.CameraTween then
            old.CameraTween:Cancel()
        end

        if old.FlightForce then
            old.FlightForce:Destroy()
        end

        if old.FlightAttachment then
            old.FlightAttachment:Destroy()
        end
    end

    getgenv().LemonTreeScript = {
        Running = true,
        AutoCollecting = false,
        InputConnection = nil,
        DescendantConnection = nil,
        DescendantRemovingConnection = nil,
        FlightConnection = nil,
        RescanConnection = nil,
        FlightForce = nil,
        FlightAttachment = nil,
        CameraTween = nil
    }
end

local ScriptState

if getgenv then
    ScriptState = getgenv().LemonTreeScript
else
    ScriptState = {
        Running = true,
        AutoCollecting = false
    }
end

local FIXED_Y = 3.7
local TELEPORT_OFFSET = 5
local CAMERA_TWEEN_TIME = 0.05
local FLIGHT_FORCE_MULTIPLIER = 1
local FRUIT_DELAY = 0.05
local SEARCH_DELAY = 0.03
local FRUIT_REACTION_TIME = 0.2
local CLICK_DELAY = 0.02
local VISIBILITY_ATTEMPTS = 16
local RESCAN_INTERVAL = 60

local ZONE_MIN_X = -302.91552734375
local ZONE_MAX_X = 302.94000244140625
local ZONE_MIN_Z = -457.056884765625
local ZONE_MAX_Z = 457.1495056152344

local ZONE_MARGIN = 2

local TELEPORT_MIN_X =
    ZONE_MIN_X + ZONE_MARGIN

local TELEPORT_MAX_X =
    ZONE_MAX_X - ZONE_MARGIN

local TELEPORT_MIN_Z =
    ZONE_MIN_Z + ZONE_MARGIN

local TELEPORT_MAX_Z =
    ZONE_MAX_Z - ZONE_MARGIN

local trees = {}
local fruitCache = {}
local fruitStates = {}
local previousFruitPresence = {}
local lastRescan = 0

local VirtualInputManager

pcall(function()
    VirtualInputManager =
        game:GetService("VirtualInputManager")
end)

local function isRunning()
    return ScriptState.Running == true
end

local function getVisualFruit(clickPart)
    if not clickPart then
        return nil
    end

    local fruit = clickPart.Parent

    if not fruit then
        return nil
    end

    if fruit.Name ~= "Fruit" then
        return nil
    end

    if not fruit:IsA("BasePart") then
        return nil
    end

    return fruit
end

local function isClickFruitPart(object)
    if not object then
        return false
    end

    if object.Name ~= "ClickFruitPart" then
        return false
    end

    if not object:IsA("BasePart") then
        return false
    end

    local fruit = object.Parent

    if not fruit then
        return false
    end

    if fruit.Name ~= "Fruit" then
        return false
    end

    if not fruit:IsA("BasePart") then
        return false
    end

    local detector =
        object:FindFirstChildOfClass("ClickDetector")

    if not detector then
        return false
    end

    return true
end

local function addTree(tree)
    if not isRunning() then
        return
    end

    if not tree then
        return
    end

    if tree.Name ~= "LemonTree" then
        return
    end

    if not tree:IsA("Model") then
        return
    end

    if not table.find(trees, tree) then
        trees[#trees + 1] = tree
    end
end

local function addFruitToCache(object)
    if not isRunning() then
        return
    end

    if not isClickFruitPart(object) then
        return
    end

    local fruit = object.Parent

    if not fruit then
        return
    end

    local lemonTree =
        fruit:FindFirstAncestor("LemonTree")

    if not lemonTree then
        return
    end

    if not lemonTree:IsA("Model") then
        return
    end

    if not lemonTree:IsDescendantOf(workspace) then
        return
    end

    fruitCache[object] = true
end

local function removeFruitFromCache(object)
    if object then
        fruitCache[object] = nil
    end
end

local function scanContainer(container)
    if not isRunning() then
        return
    end

    if not container then
        return
    end

    if container.Name == "LemonTree"
        and container:IsA("Model") then

        addTree(container)

        for _, object in ipairs(
            container:GetDescendants()
        ) do

            if not isRunning() then
                return
            end

            if isClickFruitPart(object) then
                addFruitToCache(object)
            end
        end

        return
    end

    for _, child in ipairs(
        container:GetChildren()
    ) do

        if not isRunning() then
            return
        end

        if child.Name == "LemonTree"
            and child:IsA("Model") then

            scanContainer(child)

        elseif child:IsA("Folder")
            or child:IsA("Model") then

            scanContainer(child)
        end
    end
end

local function rebuildTreeList()
    if not isRunning() then
        return
    end

    local newTrees = {}
    local newTreeSet = {}

    for i = 1, 9 do
        if not isRunning() then
            return
        end

        local tycoon =
            workspace:FindFirstChild(
                "Tycoon" .. i
            )

        if tycoon then
            for _, object in ipairs(
                tycoon:GetDescendants()
            ) do

                if object.Name == "LemonTree"
                    and object:IsA("Model") then

                    if not newTreeSet[object] then
                        newTreeSet[object] = true
                        newTrees[#newTrees + 1] =
                            object
                    end
                end
            end
        end
    end

    local directTree =
        workspace:FindFirstChild(
            "LemonTree"
        )

    if directTree
        and directTree:IsA("Model") then

        if not newTreeSet[directTree] then
            newTreeSet[directTree] = true
            newTrees[#newTrees + 1] =
                directTree
        end
    end

    trees = newTrees
end

local function rebuildFruitCache()
    if not isRunning() then
        return
    end

    local oldPresence =
        previousFruitPresence

    local newCache = {}
    local newPresence = {}

    for _, tree in ipairs(trees) do

        if tree
            and tree.Parent
            and tree:IsDescendantOf(workspace) then

            for _, object in ipairs(
                tree:GetDescendants()
            ) do

                if not isRunning() then
                    return
                end

                if isClickFruitPart(object) then

                    newCache[object] = true
                    newPresence[object] = true

                    if not oldPresence[object] then
                        fruitStates[object] = nil
                    end
                end
            end
        end
    end

    for fruit in pairs(fruitStates) do
        if not newPresence[fruit] then
            fruitStates[fruit] = nil
        end
    end

    fruitCache = newCache
    previousFruitPresence = newPresence
end

local function fullRescan()
    if not isRunning() then
        return
    end

    rebuildTreeList()
    rebuildFruitCache()

    lastRescan = os.clock()
end

fullRescan()

ScriptState.DescendantConnection =
    workspace.DescendantAdded:Connect(
        function(object)

            if not isRunning() then
                return
            end

            if object.Name == "LemonTree"
                and object:IsA("Model") then

                addTree(object)

                for _, child in ipairs(
                    object:GetDescendants()
                ) do

                    if isClickFruitPart(child) then
                        addFruitToCache(child)
                    end
                end

                return
            end

            if isClickFruitPart(object) then
                addFruitToCache(object)
            end
        end
    )

ScriptState.DescendantRemovingConnection =
    workspace.DescendantRemoving:Connect(
        function(object)

            removeFruitFromCache(object)

        end
    )

ScriptState.RescanConnection =
    RunService.Heartbeat:Connect(
        function()

            if not isRunning() then
                return
            end

            if not ScriptState.AutoCollecting then
                return
            end

            if os.clock() - lastRescan
                >= RESCAN_INTERVAL then

                fullRescan()

            end
        end
    )

local function isFruitValid(clickPart)

    if not clickPart then
        return false
    end

    if not clickPart.Parent then
        return false
    end

    if not clickPart:IsDescendantOf(workspace) then
        return false
    end

    local detector =
        clickPart:FindFirstChildOfClass(
            "ClickDetector"
        )

    if not detector then
        return false
    end

    local fruit =
        getVisualFruit(clickPart)

    if not fruit then
        return false
    end

    if not fruit:IsDescendantOf(workspace) then
        return false
    end

    return true
end

local function isFruitActuallyVisible(clickPart)

    if not isFruitValid(clickPart) then
        return false
    end

    local fruit =
        getVisualFruit(clickPart)

    if not fruit then
        return false
    end

    if fruit.Transparency >= 0.95 then
        return false
    end

    if fruit.Size.Magnitude < 0.05 then
        return false
    end

    return true
end

local function isPositionInsideZone(position)

    return
        position.X >= TELEPORT_MIN_X
        and
        position.X <= TELEPORT_MAX_X
        and
        position.Z >= TELEPORT_MIN_Z
        and
        position.Z <= TELEPORT_MAX_Z
end

local function getCandidatePosition(
    fruit,
    angle
)

    local radians =
        math.rad(angle)

    local direction =
        Vector3.new(
            math.cos(radians),
            0,
            math.sin(radians)
        )

    local position =
        fruit.Position
        + direction * TELEPORT_OFFSET

    return Vector3.new(
        position.X,
        FIXED_Y,
        position.Z
    )
end

local function canReachFruit(fruit)

    if not isFruitValid(fruit) then
        return false
    end

    for attempt = 0,
        VISIBILITY_ATTEMPTS - 1
    do

        local angle =
            attempt
            * (
                360
                / VISIBILITY_ATTEMPTS
            )

        local candidate =
            getCandidatePosition(
                fruit,
                angle
            )

        if isPositionInsideZone(candidate) then
            return true
        end
    end

    return false
end

local function getFruitState(fruit)

    local state =
        fruitStates[fruit]

    if not state then
        return nil
    end

    if state.Position then

        local distance =
            (
                fruit.Position
                - state.Position
            ).Magnitude

        if distance > 1 then
            fruitStates[fruit] = nil
            return nil
        end
    end

    return state
end

local function skipFruit(fruit)

    if not fruit then
        return
    end

    fruitStates[fruit] = {
        Skipped = true,
        Position = fruit.Position
    }
end

local function canUseFruit(fruit)

    if not isFruitValid(fruit) then
        return false
    end

    local state =
        getFruitState(fruit)

    if state
        and state.Skipped then

        return false
    end

    if not isFruitActuallyVisible(fruit) then

        skipFruit(fruit)

        return false
    end

    if not canReachFruit(fruit) then

        skipFruit(fruit)

        return false
    end

    return true
end

local function getNearestFruit()

    if not isRunning() then
        return nil
    end

    local character =
        player.Character

    if not character then
        return nil
    end

    local root =
        character:FindFirstChild(
            "HumanoidRootPart"
        )

    if not root then
        return nil
    end

    local nearest = nil
    local nearestDistance = math.huge

    for fruit in pairs(fruitCache) do

        if not isFruitValid(fruit) then

            fruitCache[fruit] = nil

        elseif canUseFruit(fruit) then

            local visualFruit =
                getVisualFruit(fruit)

            if visualFruit then

                local distance =
                    (
                        root.Position
                        - visualFruit.Position
                    ).Magnitude

                if distance <
                    nearestDistance then

                    nearestDistance =
                        distance

                    nearest =
                        fruit
                end
            end
        end
    end

    return nearest
end

local function findBestPosition(fruit)

    if not isFruitValid(fruit) then
        return nil
    end

    local character =
        player.Character

    if not character then
        return nil
    end

    local root =
        character:FindFirstChild(
            "HumanoidRootPart"
        )

    if not root then
        return nil
    end

    local offset =
        root.Position
        - fruit.Position

    local horizontal =
        Vector3.new(
            offset.X,
            0,
            offset.Z
        )

    local startAngle = 0

    if horizontal.Magnitude > 0.1 then

        startAngle =
            math.deg(
                math.atan2(
                    horizontal.Z,
                    horizontal.X
                )
            )
    end

    for attempt = 0,
        VISIBILITY_ATTEMPTS - 1
    do

        local angle =
            startAngle
            + (
                attempt
                * (
                    360
                    / VISIBILITY_ATTEMPTS
                )
            )

        local candidate =
            getCandidatePosition(
                fruit,
                angle
            )

        if isPositionInsideZone(candidate) then
            return candidate
        end
    end

    return nil
end

local function teleportToFruit(fruit)

    if not isRunning() then
        return false
    end

    if not isFruitValid(fruit) then
        return false
    end

    local targetPosition =
        findBestPosition(fruit)

    if not targetPosition then

        skipFruit(fruit)

        return false
    end

    local character =
        player.Character

    if not character then
        return false
    end

    local root =
        character:FindFirstChild(
            "HumanoidRootPart"
        )

    if not root then
        return false
    end

    root.CFrame =
        CFrame.new(
            targetPosition
        )

    RunService.Heartbeat:Wait()

    if not isFruitActuallyVisible(fruit) then

        skipFruit(fruit)

        return false
    end

    return true
end

local function turnCameraToFruit(fruit)

    if not isRunning() then
        return false
    end

    if not isFruitValid(fruit) then
        return false
    end

    local camera =
        workspace.CurrentCamera

    if not camera then
        return false
    end

    local visualFruit =
        getVisualFruit(fruit)

    if not visualFruit then
        return false
    end

    if ScriptState.CameraTween then

        ScriptState.CameraTween:Cancel()
        ScriptState.CameraTween = nil

    end

    local cameraPosition =
        camera.CFrame.Position

    local direction =
        visualFruit.Position
        - cameraPosition

    if direction.Magnitude < 0.01 then
        return false
    end

    direction =
        direction.Unit

    local targetCFrame =
        CFrame.lookAt(
            cameraPosition,
            cameraPosition
                + direction,
            Vector3.yAxis
        )

    local tween =
        TweenService:Create(
            camera,
            TweenInfo.new(
                CAMERA_TWEEN_TIME,
                Enum.EasingStyle.Linear,
                Enum.EasingDirection.Out
            ),
            {
                CFrame = targetCFrame
            }
        )

    ScriptState.CameraTween =
        tween

    tween.Completed:Connect(
        function()

            if ScriptState.CameraTween ==
                tween then

                if isFruitValid(fruit) then

                    local currentCamera =
                        workspace.CurrentCamera

                    local currentFruit =
                        getVisualFruit(fruit)

                    if currentCamera
                        and currentFruit then

                        local position =
                            currentCamera.CFrame.Position

                        local finalDirection =
                            currentFruit.Position
                            - position

                        if finalDirection.Magnitude
                            > 0.01 then

                            currentCamera.CFrame =
                                CFrame.lookAt(
                                    position,
                                    position
                                        + finalDirection.Unit,
                                    Vector3.yAxis
                                )
                        end
                    end
                end

                ScriptState.CameraTween =
                    nil
            end
        end
    )

    tween:Play()

    return true
end

local function isCameraLookingAtFruit(fruit)

    if not isFruitActuallyVisible(fruit) then
        return false
    end

    local camera =
        workspace.CurrentCamera

    if not camera then
        return false
    end

    local visualFruit =
        getVisualFruit(fruit)

    if not visualFruit then
        return false
    end

    local params =
        RaycastParams.new()

    params.FilterType =
        Enum.RaycastFilterType.Exclude

    params.IgnoreWater = true

    local filter = {}

    if player.Character then
        filter[#filter + 1] =
            player.Character
    end

    params.FilterDescendantsInstances =
        filter

    local origin =
        camera.CFrame.Position

    local direction =
        visualFruit.Position
        - origin

    if direction.Magnitude < 0.01 then
        return true
    end

    local result =
        workspace:Raycast(
            origin,
            direction,
            params
        )

    if not result then
        return true
    end

    if result.Instance ==
        visualFruit then

        return true
    end

    if result.Instance ==
        fruit then

        return true
    end

    return false
end

local function simulateMouseClick(fruit)

    if not isRunning() then
        return false
    end

    if not isFruitValid(fruit) then
        return false
    end

    local camera =
        workspace.CurrentCamera

    if not camera then
        return false
    end

    local visualFruit =
        getVisualFruit(fruit)

    if not visualFruit then
        return false
    end

    local screenPosition,
        onScreen =
        camera:WorldToScreenPoint(
            visualFruit.Position
        )

    if not onScreen then
        return false
    end

    local x =
        math.floor(
            screenPosition.X
        )

    local y =
        math.floor(
            screenPosition.Y
        )

    if x < 0
        or y < 0
        or x > camera.ViewportSize.X
        or y > camera.ViewportSize.Y then

        return false
    end

    if VirtualInputManager then

        local moveOk =
            pcall(
                function()

                    VirtualInputManager:
                        SendMouseMoveEvent(
                            x,
                            y,
                            game
                        )

                end
            )

        if not moveOk then
            return false
        end

        task.wait(CLICK_DELAY)

        local downOk =
            pcall(
                function()

                    VirtualInputManager:
                        SendMouseButtonEvent(
                            x,
                            y,
                            0,
                            true,
                            game,
                            0
                        )

                end
            )

        if not downOk then
            return false
        end

        task.wait(CLICK_DELAY)

        local upOk =
            pcall(
                function()

                    VirtualInputManager:
                        SendMouseButtonEvent(
                            x,
                            y,
                            0,
                            false,
                            game,
                            0
                        )

                end
            )

        if not upOk then
            return false
        end

        return true
    end

    if mouse1click then

        local ok =
            pcall(
                function()
                    mouse1click()
                end
            )

        if ok then
            return true
        end
    end

    return false
end

local function waitForFruitReaction(fruit)

    local startTime =
        os.clock()

    local initialPosition =
        fruit.Position

    while
        isRunning()
        and
        ScriptState.AutoCollecting
        and
        os.clock() - startTime
            < FRUIT_REACTION_TIME
    do

        if not isFruitValid(fruit) then
            return true
        end

        if not isFruitActuallyVisible(fruit) then
            return true
        end

        if (
            fruit.Position
            - initialPosition
        ).Magnitude > 0.05 then

            return true
        end

        RunService.Heartbeat:Wait()
    end

    return false
end

local function processFruit(fruit)

    if not isRunning() then
        return false
    end

    if not ScriptState.AutoCollecting then
        return false
    end

    if not isFruitValid(fruit) then
        return false
    end

    local state =
        getFruitState(fruit)

    if state
        and state.Skipped then

        return false
    end

    fruitStates[fruit] = {
        Skipped = true,
        Position = fruit.Position
    }

    if not teleportToFruit(fruit) then
        return false
    end

    RunService.RenderStepped:Wait()

    if not turnCameraToFruit(fruit) then
        return false
    end

    task.wait(
        CAMERA_TWEEN_TIME
    )

    if not isCameraLookingAtFruit(fruit) then
        return false
    end

    task.wait(FRUIT_DELAY)

    if not simulateMouseClick(fruit) then
        return false
    end

    return waitForFruitReaction(fruit)
end

local function enableFlight()

    if not isRunning() then
        return
    end

    local character =
        player.Character

    if not character then
        return
    end

    local root =
        character:FindFirstChild(
            "HumanoidRootPart"
        )

    if not root then
        return
    end

    if ScriptState.FlightForce then
        ScriptState.FlightForce:Destroy()
        ScriptState.FlightForce = nil
    end

    if ScriptState.FlightAttachment then
        ScriptState.FlightAttachment:Destroy()
        ScriptState.FlightAttachment = nil
    end

    local attachment =
        Instance.new(
            "Attachment"
        )

    attachment.Name =
        "LemonFlightAttachment"

    attachment.Parent =
        root

    ScriptState.FlightAttachment =
        attachment

    local force =
        Instance.new(
            "VectorForce"
        )

    force.Name =
        "LemonFlightForce"

    force.Attachment0 =
        attachment

    force.RelativeTo =
        Enum.ActuatorRelativeTo.World

    force.ApplyAtCenterOfMass =
        true

    force.Force =
        Vector3.new(
            0,
            root.AssemblyMass
                * workspace.Gravity
                * FLIGHT_FORCE_MULTIPLIER,
            0
        )

    force.Parent =
        root

    ScriptState.FlightForce =
        force
end

local function disableFlight()

    if ScriptState.FlightForce then
        ScriptState.FlightForce:Destroy()
        ScriptState.FlightForce = nil
    end

    if ScriptState.FlightAttachment then
        ScriptState.FlightAttachment:Destroy()
        ScriptState.FlightAttachment = nil
    end
end

ScriptState.FlightConnection =
    RunService.Heartbeat:Connect(
        function()

            if not isRunning() then
                return
            end

            local character =
                player.Character

            if not character then
                return
            end

            local root =
                character:FindFirstChild(
                    "HumanoidRootPart"
                )

            if not root then
                return
            end

            if ScriptState.FlightForce then

                ScriptState.FlightForce.Force =
                    Vector3.new(
                        0,
                        root.AssemblyMass
                            * workspace.Gravity
                            * FLIGHT_FORCE_MULTIPLIER,
                        0
                    )
            end
        end
    )

local function autoCollectLoop()

    enableFlight()

    while
        isRunning()
        and
        ScriptState.AutoCollecting
    do

        local ok =
            pcall(
                function()

                    if os.clock() - lastRescan
                        >= RESCAN_INTERVAL then

                        fullRescan()

                    end

                    local fruit =
                        getNearestFruit()

                    if not fruit then

                        fullRescan()

                        fruit =
                            getNearestFruit()

                    end

                    if fruit then
                        processFruit(fruit)
                    end
                end
            )

        task.wait(SEARCH_DELAY)
    end
end

ScriptState.InputConnection =
    UserInputService.InputBegan:Connect(
        function(
            input,
            gameProcessed
        )

            if not isRunning() then
                return
            end

            if gameProcessed then
                return
            end

            if input.KeyCode
                ~= Enum.KeyCode.Y then

                return
            end

            if ScriptState.AutoCollecting then

                ScriptState.AutoCollecting =
                    false

                if ScriptState.CameraTween then
                    ScriptState.CameraTween:Cancel()
                    ScriptState.CameraTween = nil
                end

                disableFlight()

                return
            end

            ScriptState.AutoCollecting =
                true

            lastRescan = 0

            task.spawn(
                autoCollectLoop
            )
        end
    )

player.CharacterAdded:Connect(
    function()

        if not isRunning() then
            return
        end

        fruitStates = {}
        previousFruitPresence = {}

        task.wait(1)

        fullRescan()

        if ScriptState.AutoCollecting then
            enableFlight()
        end
    end
)

Features & Information

auto lemon collect
#exploit#auto#Sell lemons

Community Comments (0)

No comments yet for this script.

More Scripts for Sell Lemons 🍋