Open Source
Keyless

Open Source

[๐Ÿ’ฉ] Poop a Big Poop ๐ŸงปProject_CrypticProject_Cryptic 357 views 354 executesUpdated Oct 1, 2026
5.0/ 5(3 votes)
30100% Positive
Lua Scriptโ€ข728 lines (19355 chars)
if getgenv().AutoPoopCleanup then
    pcall(getgenv().AutoPoopCleanup)
    getgenv().AutoPoopCleanup = nil
end

if getgenv().AutoPoopLibrary then
    pcall(function()
        getgenv().AutoPoopLibrary:Unload()
    end)
    getgenv().AutoPoopLibrary = nil
end

local libraryUrl = "https://raw.githubusercontent.com/croksyscript/CrypticLoader/refs/heads/main/Obsidian/Obsidian_UI/Obsidian_UI.lua"

local success, Library = pcall(function()
    return loadstring(game:HttpGet(libraryUrl))()
end)

if not success or not Library then
    return
end

getgenv().AutoPoopLibrary = Library

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local GuiService = game:GetService("GuiService")
local RunService = game:GetService("RunService")
local VirtualInputManager = game:GetService("VirtualInputManager")

local LocalPlayer = Players.LocalPlayer
local PlayerScripts = LocalPlayer:WaitForChild("PlayerScripts")
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local Packets = require(ReplicatedStorage:WaitForChild("Packets"))
local minigameActive = PlayerScripts:WaitForChild("IS_MINIGAME_ACTIVE")

local okFood, FoodData = pcall(require, ReplicatedStorage:WaitForChild("FoodData"))
local okMoney, FormatMoney = pcall(require, ReplicatedStorage:WaitForChild("FormatMoney"))

local PoopUI = PlayerGui:WaitForChild("PoopUI")
local lineTrigger = PoopUI:WaitForChild("CatchBar"):WaitForChild("LineTrigger")
local slider = PoopUI.CatchBar:WaitForChild("BarLine"):WaitForChild("Slider")
local target = slider:WaitForChild("Target")

local BACKPACK_LIMIT = 300

local state = {
    running = true,
    notifications = {},
    remotePoop = false,
    legitPoop = false,
    instantLine = false,
    remoteDelay = 1,
    pause = 2,
    cycles = 0,
    autoSell = false,
    sellMode = "Poop Count",
    sellValue = 100,
    sellAction = "Sell All",
    sellOneMode = "First",
    lastSell = os.clock(),
    autoBuy = false,
    buyInterval = 10,
    selectedFoods = {},
    stock = {},
}

local connections = {}

local function jitter(minValue, maxValue)
    return minValue + math.random() * (maxValue - minValue)
end

local function formatMoney(value)
    if okMoney and typeof(value) == "number" then
        local ok, text = pcall(FormatMoney, value, true)
        if ok then
            return text
        end
    end
    return tostring(value)
end

local function isPoop(tool)
    return tool:IsA("Tool") and tool.Name:sub(1, 4) == "Poop"
end

local function getPoops()
    local list = {}
    for _, tool in ipairs(LocalPlayer.Backpack:GetChildren()) do
        if isPoop(tool) then
            table.insert(list, tool)
        end
    end
    local character = LocalPlayer.Character
    local held = character and character:FindFirstChildOfClass("Tool")
    if held and isPoop(held) then
        table.insert(list, held)
    end
    return list
end

local function getBackpackSize()
    return #LocalPlayer.Backpack:GetChildren()
end

local function getWeight(tool)
    return tonumber(tool.Name:match("([%d%.]+)%s*lb")) or 0
end

local CLICK_LATENCY = 0.05

local lastCenter = 0
local lastTime = os.clock()

local function isLineInTarget()
    local now = os.clock()
    local center = lineTrigger.AbsolutePosition.X + lineTrigger.AbsoluteSize.X / 2
    local elapsed = math.max(now - lastTime, 1 / 240)
    local velocity = (center - lastCenter) / elapsed
    lastCenter = center
    lastTime = now
    local predicted = center + velocity * CLICK_LATENCY
    local margin = lineTrigger.AbsoluteSize.X * 0.065
    local left = target.AbsolutePosition.X
    return left - margin < predicted and predicted < left + target.AbsoluteSize.X + margin
end

local function sendMouse(position, down)
    VirtualInputManager:SendMouseButtonEvent(position.X, position.Y, 0, down, game, 0)
end

local CLICK_SPOTS = {}

for _, x in ipairs({ 0.04, 0.96, 0.08, 0.92 }) do
    for _, y in ipairs({ 0.35, 0.5, 0.25, 0.65, 0.75 }) do
        table.insert(CLICK_SPOTS, Vector2.new(x, y))
    end
end

local function isSpotFree(point)
    local inset = GuiService:GetGuiInset()
    for _, gui in ipairs(PlayerGui:GetGuiObjectsAtPosition(point.X - inset.X, point.Y - inset.Y)) do
        if not gui:IsDescendantOf(PoopUI) and (gui:IsA("GuiButton") or gui.Active) then
            return false
        end
    end
    return true
end

local function getFreePoint()
    local size = workspace.CurrentCamera.ViewportSize
    for _, spot in ipairs(CLICK_SPOTS) do
        local point = size * spot
        if isSpotFree(point) then
            return point
        end
    end
    return nil
end

local function clickTrigger()
    local position = getFreePoint()
    if not position then
        return
    end
    sendMouse(position, true)
    task.wait(0.03)
    sendMouse(position, false)
end

local function getChargeFill()
    local chargeUi = workspace:FindFirstChild("ChargeUI")
    local bar = chargeUi and chargeUi:FindFirstChild("BarProgress", true)
    return bar and bar:FindFirstChild("Fill")
end

local function chargeBar()
    local position = getFreePoint()
    if not position then
        task.wait(1)
        return
    end
    sendMouse(position, true)
    local startTime = os.clock()
    local fill
    repeat
        task.wait()
        fill = getChargeFill()
    until fill or os.clock() - startTime > 0.5
    while os.clock() - startTime < 2 do
        if fill and fill.Parent and fill.Size.Y.Scale >= 0.97 then
            break
        end
        if not fill and os.clock() - startTime >= 0.7 then
            break
        end
        task.wait()
    end
    sendMouse(position, false)
end

local targetAspect = target:FindFirstChildOfClass("UIAspectRatioConstraint")
local defaultAspectRatio = targetAspect and targetAspect.AspectRatio
local WIDE_ASPECT_RATIO = 4

local function moveTargetToLine()
    local lineCenter = lineTrigger.AbsolutePosition.X + lineTrigger.AbsoluteSize.X / 2
    local targetCenter = target.AbsolutePosition.X + target.AbsoluteSize.X / 2
    local position = slider.Position
    slider.Position = UDim2.new(position.X.Scale, position.X.Offset + lineCenter - targetCenter, position.Y.Scale, position.Y.Offset)
end

local function widenTarget()
    if targetAspect then
        targetAspect.AspectRatio = WIDE_ASPECT_RATIO
    end
end

local function restoreTarget()
    if targetAspect then
        targetAspect.AspectRatio = defaultAspectRatio
    end
end

local function runLegitCycle()
    if not minigameActive.Value then
        chargeBar()
        task.wait(0.3)
    end
    local deadline = os.clock() + 30
    while state.running and minigameActive.Value and os.clock() < deadline do
        if state.instantLine then
            widenTarget()
            moveTargetToLine()
            RunService.Heartbeat:Wait()
            moveTargetToLine()
            clickTrigger()
            task.wait(jitter(0.2, 0.3))
        elseif isLineInTarget() then
            clickTrigger()
            task.wait(jitter(0.4, 0.55))
        end
        task.wait()
    end
    restoreTarget()
    state.cycles += 1
    task.wait(state.pause * jitter(0.85, 1.25))
end

local function runRemoteCycle()
    Packets.RequestPoop:Fire()
    state.cycles += 1
    local delay = state.remoteDelay * jitter(0.8, 1.35)
    if math.random() < 0.05 then
        delay += jitter(2, 4)
    end
    task.wait(delay)
end

local function pickPoop(mode)
    local poops = getPoops()
    if #poops == 0 then
        return nil
    end
    if mode == "Held" then
        local character = LocalPlayer.Character
        local held = character and character:FindFirstChildOfClass("Tool")
        return held and isPoop(held) and held or nil
    end
    if mode == "Smallest" or mode == "Biggest" then
        table.sort(poops, function(a, b)
            if mode == "Smallest" then
                return getWeight(a) < getWeight(b)
            end
            return getWeight(a) > getWeight(b)
        end)
    end
    return poops[1]
end

local function sellOne(mode)
    local tool = pickPoop(mode)
    local uuid = tool and tool:GetAttribute("uniquePoopID")
    if not uuid then
        return false
    end
    local ok, result = pcall(function()
        return Packets.SellCurrentlyHeldPoop:Fire(uuid)
    end)
    if ok then
        Library:Notify("Sold poop for " .. formatMoney(result), 3)
    end
    return ok
end

local function sellAll()
    local ok, result = pcall(function()
        return Packets.SellInventory:Fire()
    end)
    if ok then
        state.lastSell = os.clock()
        Library:Notify("Sold inventory for " .. formatMoney(result), 3)
    end
    return ok
end

local function runSell()
    if state.sellAction == "Sell One" then
        return sellOne(state.sellOneMode == "Held" and "First" or state.sellOneMode)
    end
    return sellAll()
end

local function refreshStock()
    pcall(function()
        Packets.FoodStock:Fire()
    end)
end

local function buyFood(name)
    pcall(function()
        Packets.PurchaseFood:Fire(name)
    end)
end

local function getFoodNames()
    local names = {}
    if okFood and typeof(FoodData) == "table" then
        for name in pairs(FoodData) do
            table.insert(names, name)
        end
        table.sort(names, function(a, b)
            return FoodData[a].Price < FoodData[b].Price
        end)
    end
    return names
end

local function getStockText()
    local names = {}
    for name in pairs(state.stock) do
        table.insert(names, name)
    end
    table.sort(names)
    return #names > 0 and table.concat(names, ", ") or "Nothing"
end

table.insert(connections, Packets.FoodStock.OnClientEvent:Connect(function(list)
    state.stock = {}
    if typeof(list) == "table" then
        for _, name in ipairs(list) do
            state.stock[name] = true
        end
    end
end))

table.insert(connections, Packets.PurchaseFood.OnClientEvent:Connect(function(purchased, name)
    if purchased then
        state.stock[name] = nil
        table.insert(state.notifications, "Bought " .. tostring(name))
    end
end))

task.spawn(function()
    while state.running do
        local hasSpace = getBackpackSize() < BACKPACK_LIMIT
        local cycle = nil
        if hasSpace and state.remotePoop then
            cycle = runRemoteCycle
        elseif state.legitPoop and (hasSpace or minigameActive.Value) then
            cycle = runLegitCycle
        end
        if cycle then
            local ok = pcall(cycle)
            if not ok then
                task.wait(1)
            end
        else
            task.wait(0.3)
        end
    end
end)

task.spawn(function()
    while state.running do
        if state.autoSell then
            if state.sellMode == "Seconds" then
                if os.clock() - state.lastSell >= state.sellValue then
                    state.lastSell = os.clock()
                    runSell()
                end
            elseif #getPoops() >= state.sellValue then
                runSell()
                task.wait(2)
            end
        end
        task.wait(0.5)
    end
end)

task.spawn(function()
    while state.running do
        local text = table.remove(state.notifications, 1)
        if text then
            Library:Notify(text, 3)
        end
        task.wait(0.3)
    end
end)

local lastBuyCheck = 0

task.spawn(function()
    while state.running do
        local due = os.clock() - lastBuyCheck >= state.buyInterval
        if state.autoBuy and due and next(state.selectedFoods) then
            lastBuyCheck = os.clock()
            refreshStock()
            task.wait(1)
            for name in pairs(state.selectedFoods) do
                if state.stock[name] then
                    buyFood(name)
                    task.wait(jitter(0.5, 0.9))
                end
            end
        end
        task.wait(0.5)
    end
end)

local Window = Library:CreateWindow({
    Title = "Open Source - Poop a Big Poop",
    Footer = ".gg/XDpsSW7Ybs",
    Icon = 120217226033572,
    NotifySide = "Right",
    Center = true,
    AutoShow = true,
    ToggleKeybind = Enum.KeyCode.RightControl,
    Folder = "Poop",
})

local function buildPoopTab(Tab)
    local Box = Tab:AddGroupbox({
        Side = "Left",
        Name = "Auto Poop",
        IconName = "zap",
    })

    Box:AddToggle("RemotePoopToggle", {
        Text = "Auto Poop (Remote)",
        Default = false,
        Tooltip = "Fast, sends the poop request directly",
        Callback = function(value)
            state.remotePoop = value
            if value and Library.Toggles.LegitPoopToggle.Value then
                Library.Toggles.LegitPoopToggle:SetValue(false)
            end
        end,
    })

    Box:AddSlider("RemoteDelay", {
        Text = "Remote Delay",
        Default = 1,
        Min = 0.3,
        Max = 5,
        Rounding = 1,
        Suffix = "s",
        Tooltip = "Lower values are faster but riskier",
        Callback = function(value)
            state.remoteDelay = value
        end,
    })

    Box:AddDivider("Legit")

    Box:AddToggle("LegitPoopToggle", {
        Text = "Auto Poop (Legit)",
        Default = false,
        Tooltip = "Charges the bar and clicks the minigame like a player",
        Callback = function(value)
            state.legitPoop = value
            if value and Library.Toggles.RemotePoopToggle.Value then
                Library.Toggles.RemotePoopToggle:SetValue(false)
            end
        end,
    })

    Box:AddToggle("InstantLineToggle", {
        Text = "Instant Line",
        Default = false,
        Tooltip = "Moves the target under the line before every click",
        Callback = function(value)
            state.instantLine = value
        end,
    })

    Box:AddSlider("PoopPause", {
        Text = "Legit Pause",
        Default = 2,
        Min = 0.1,
        Max = 10,
        Rounding = 1,
        Suffix = "s",
        Callback = function(value)
            state.pause = value
        end,
    })

    local Info = Tab:AddGroupbox({
        Side = "Right",
        Name = "Info",
        IconName = "info",
    })

    local statusLabel = Info:AddLabel("Poops: 0")
    local cycleLabel = Info:AddLabel("Poops Made: 0")
    local sizeLabel = Info:AddLabel("Inventory: 0 / " .. BACKPACK_LIMIT)

    task.spawn(function()
        while state.running do
            statusLabel:SetText("Poops: " .. #getPoops())
            cycleLabel:SetText("Poops Made: " .. state.cycles)
            sizeLabel:SetText(("Inventory: %d / %d"):format(getBackpackSize(), BACKPACK_LIMIT))
            task.wait(0.5)
        end
    end)
end

local function buildSellTab(Tab)
    local Manual = Tab:AddGroupbox({
        Side = "Left",
        Name = "Manual Sell",
        IconName = "hand-coins",
    })

    Manual:AddButton({
        Text = "Sell All Poops",
        Func = sellAll,
    })

    Manual:AddDropdown("SellOneMode", {
        Text = "Sell One Mode",
        Values = { "First", "Smallest", "Biggest", "Held" },
        Default = 1,
        Callback = function(value)
            state.sellOneMode = value
        end,
    })

    Manual:AddButton({
        Text = "Sell One Poop",
        Func = function()
            if not sellOne(state.sellOneMode) then
                Library:Notify("No matching poop found", 3)
            end
        end,
    })

    local Auto = Tab:AddGroupbox({
        Side = "Right",
        Name = "Auto Sell",
        IconName = "repeat",
    })

    Auto:AddToggle("AutoSellToggle", {
        Text = "Auto Sell",
        Default = false,
        Callback = function(value)
            state.autoSell = value
            state.lastSell = os.clock()
        end,
    })

    Auto:AddDropdown("AutoSellMode", {
        Text = "Sell Trigger",
        Values = { "Poop Count", "Seconds" },
        Default = 1,
        Callback = function(value)
            state.sellMode = value
        end,
    })

    Auto:AddInput("AutoSellValue", {
        Text = "Poops or Seconds",
        Default = "100",
        Numeric = true,
        Finished = true,
        Placeholder = "100",
        Callback = function(value)
            state.sellValue = math.max(tonumber(value) or 1, 1)
        end,
    })

    Auto:AddDropdown("AutoSellAction", {
        Text = "Sell Action",
        Values = { "Sell All", "Sell One" },
        Default = 1,
        Callback = function(value)
            state.sellAction = value
        end,
    })

    Auto:AddLabel({
        Text = "Stand near the sell NPC",
        DoesWrap = true,
    })
end

local function buildFoodTab(Tab)
    local Buy = Tab:AddGroupbox({
        Side = "Left",
        Name = "Buy Food",
        IconName = "shopping-cart",
    })

    Buy:AddDropdown("FoodSelect", {
        Text = "Foods",
        Values = getFoodNames(),
        Default = {},
        Multi = true,
        AllowNull = true,
        SelectAllButtons = true,
        Callback = function(values)
            state.selectedFoods = {}
            for name, enabled in pairs(values) do
                if enabled then
                    state.selectedFoods[name] = true
                end
            end
        end,
    })

    Buy:AddButton({
        Text = "Buy Selected Once",
        Func = function()
            refreshStock()
            task.wait(1)
            for name in pairs(state.selectedFoods) do
                if state.stock[name] then
                    buyFood(name)
                    task.wait(jitter(0.5, 0.9))
                else
                    Library:Notify(name .. " is out of stock", 3)
                end
            end
        end,
    })

    Buy:AddButton({
        Text = "Buy Everything In Stock",
        Func = function()
            refreshStock()
            task.wait(1)
            for name in pairs(state.stock) do
                buyFood(name)
                task.wait(jitter(0.5, 0.9))
            end
        end,
    })

    local Auto = Tab:AddGroupbox({
        Side = "Right",
        Name = "Auto Buy",
        IconName = "repeat",
    })

    Auto:AddToggle("AutoBuyToggle", {
        Text = "Auto Buy Selected",
        Default = false,
        Callback = function(value)
            state.autoBuy = value
        end,
    })

    Auto:AddSlider("BuyInterval", {
        Text = "Check Stock Every",
        Default = 10,
        Min = 5,
        Max = 60,
        Rounding = 0,
        Suffix = "s",
        Callback = function(value)
            state.buyInterval = value
        end,
    })

    local stockLabel = Auto:AddLabel({
        Text = "In Stock: Nothing",
        DoesWrap = true,
    })

    task.spawn(function()
        while state.running do
            stockLabel:SetText("In Stock: " .. getStockText())
            task.wait(1)
        end
    end)

    refreshStock()
end

local Tabs = {
    Poop = Window:AddTab("Poop", "zap"),
    Sell = Window:AddTab("Sell", "hand-coins"),
    Food = Window:AddTab("Food", "shopping-cart"),
}

buildPoopTab(Tabs.Poop)
buildSellTab(Tabs.Sell)
buildFoodTab(Tabs.Food)

local function cleanup()
    state.running = false
    state.remotePoop = false
    state.legitPoop = false
    state.autoSell = false
    state.autoBuy = false
    restoreTarget()
    for _, connection in ipairs(connections) do
        connection:Disconnect()
    end
    connections = {}
end

getgenv().AutoPoopCleanup = cleanup
Library:OnUnload(cleanup)

Features & Information

Open Source :D
#open source#poop#Poop a Big Poop#keyless#free

Community Comments (0)

No comments yet for this script.

More Scripts for [๐Ÿ’ฉ] Poop a Big Poop ๐Ÿงป