Harrys puzzle solver EUT OPENSOURCE
Key Required

Harrys puzzle solver EUT OPENSOURCE

Everything Upgrade TreeSasYTikSasYTik 1.5K views 179 executesUpdated Apr 26, 2026
5.0/ 5(1 votes)
10100% Positive
Lua Script•971 lines (31302 chars)
local _setIdent
do
    local names = { "setthreadidentity", "set_thread_identity", "setidentity",
                    "setcontext", "setthreadcontext" }
    for _, n in ipairs(names) do
        local f = rawget(getfenv(), n)
        if typeof(f) == "function" then _setIdent = f; break end
    end
end

local function elevate()
    if _setIdent then
        if pcall(_setIdent, 8) then return end
        if pcall(_setIdent, 7) then return end
        pcall(_setIdent, 2)
    end
end

elevate()

local _firesignal     = rawget(getfenv(), "firesignal")     or firesignal
local _getconnections = rawget(getfenv(), "getconnections") or getconnections

local function fireSignalSafely(sig, ...)
    if typeof(_firesignal) == "function" then
        pcall(_firesignal, sig, ...)
    end
    if typeof(_getconnections) == "function" then
        local ok, conns = pcall(_getconnections, sig)
        if ok and type(conns) == "table" then
            for _, conn in ipairs(conns) do
                if type(conn.Fire) == "function" then
                    pcall(conn.Fire, conn, ...)
                end
                if type(conn.Function) == "function" then
                    pcall(conn.Function, ...)
                end
            end
        end
    end
end

local function fireClick(btn)
    fireSignalSafely(btn.MouseButton1Down, 0, 0)
    fireSignalSafely(btn.MouseButton1Up,   0, 0)
    fireSignalSafely(btn.MouseButton1Click)
    fireSignalSafely(btn.Activated, nil, 1)
end

local function findScreenFrame()
    local objects = workspace:FindFirstChild("objects")
    if not objects then return nil, "workspace.objects not found" end
    local puzzle = objects:FindFirstChild("puzzle")
    if not puzzle then return nil, "puzzle not found" end
    local screen = puzzle:FindFirstChild("Screen", true)
    if not screen then return nil, "Screen part not found" end
    local sg = screen:FindFirstChildOfClass("SurfaceGui")
    if not sg then return nil, "SurfaceGui not found" end
    local sf = sg:FindFirstChild("ScreenFrame")
    if not sf then return nil, "ScreenFrame not found" end
    return sf
end

local function findButtonsContainer()
    local sf, err = findScreenFrame()
    if not sf then return nil, err end
    local b = sf:FindFirstChild("Buttons")
    if not b then return nil, "Buttons not found" end
    return b
end

local function findFormulaFrame(sf)
    for _, d in ipairs(sf:GetDescendants()) do
        if d.Name == "FormulaFrame" then return d end
    end
end

local function getFormulaText(ff)
    if not ff then return "" end
    for _, d in ipairs(ff:GetDescendants()) do
        if d:IsA("TextLabel") then
            local t = d.Text
            if t and t ~= "" and t ~= "Label" then return t end
        end
    end
    return ""
end

local function findPlayButton()
    local sf = findScreenFrame()
    if not sf then return nil end
    for _, d in ipairs(sf:GetDescendants()) do
        if d:IsA("TextButton") and (d.Name == "PlayButton" or d.Text == "START") then
            return d
        end
    end
end

local function findRegenerateBtn()
    local objects = workspace:FindFirstChild("objects")
    if not objects then return nil end
    local puzzle = objects:FindFirstChild("puzzle")
    if not puzzle then return nil end
    for _, d in ipairs(puzzle:GetDescendants()) do
        if (d:IsA("ImageButton") or d:IsA("TextButton"))
           and d.Name == "RegenerateStage" then
            return d
        end
    end
end

local function isVisibleChain(g)
    local cur = g
    while cur and cur:IsA("GuiObject") do
        if not cur.Visible then return false end
        cur = cur.Parent
    end
    return true
end

local function splitTopLevelCommas(s)
    local parts, depth, cur = {}, 0, ""
    for i = 1, #s do
        local ch = s:sub(i, i)
        if ch == "(" or ch == "[" or ch == "{" then depth = depth + 1; cur = cur .. ch
        elseif ch == ")" or ch == "]" or ch == "}" then depth = depth - 1; cur = cur .. ch
        elseif ch == "," and depth == 0 then parts[#parts + 1] = cur; cur = ""
        else cur = cur .. ch end
    end
    if cur:match("%S") then parts[#parts + 1] = cur end
    return parts
end

local function normalizeExpr(t)
    t = t:gsub("π", "math.pi")
    t = t:gsub("\226\136\146", "-")
    t = t:gsub("\226\128\147", "-")
    t = t:gsub("\226\128\148", "-")
    t = t:gsub("%)%s*%(", ")*(")
    t = t:gsub("(%d)%s*%(", "%1*(")
    t = t:gsub("%)%s*(%d)", ")*%1")
    return t
end

local function evaluateMath(text)
    if type(text) ~= "string" or text:match("^%s*$") then return nil end
    local expr = normalizeExpr(text)
    local hasAssign = expr:find("=") ~= nil
    local hasEqEq   = expr:find("==") ~= nil
    local hasNeq    = expr:find("~=") ~= nil
    local code
    if hasAssign and not hasEqEq and not hasNeq then
        local pieces, lastVar = {}, nil
        for _, p in ipairs(splitTopLevelCommas(expr)) do
            p = p:match("^%s*(.-)%s*$")
            local var = p:match("^([%a_][%w_]*)%s*=[^=]") or p:match("^([%a_][%w_]*)%s*=$")
            if not var then return nil end
            pieces[#pieces + 1] = "local " .. p
            lastVar = var
        end
        if not lastVar then return nil end
        code = table.concat(pieces, "; ") .. "; return " .. lastVar
    else
        code = "return " .. expr
    end
    local loader = loadstring or load
    if type(loader) ~= "function" then return nil end
    local fn = loader(code)
    if not fn then return nil end
    local ok, res = pcall(fn)
    if not ok or type(res) ~= "number" or res ~= res then return nil end
    return res
end

local SHIFT_MAP = {
    ["!"]="1",["@"]="2",["#"]="3",["$"]="4",["%"]="5",
    ["^"]="6",["&"]="7",["*"]="8",["("]="9",[")"]="0",
}

local function decodeShift(text)
    if type(text) ~= "string" then return nil end
    local digs = {}
    for i = 1, #text do
        local ch = text:sub(i, i)
        if ch ~= " " and ch ~= "\t" and ch ~= "\n" and ch ~= "\r" then
            local d = SHIFT_MAP[ch]
            if not d then return nil end
            digs[#digs + 1] = d
        end
    end
    if #digs == 0 then return nil end
    return tonumber(table.concat(digs))
end

local function parseBased(text)
    if type(text) ~= "string" then return nil end
    local sign, digits, base = text:match("^%s*(%-?)%s*([%w]+)%s*%(%s*(%d+)%s*%)%s*$")
    if not digits then return nil end
    base = tonumber(base)
    if not base or base < 2 or base > 36 then return nil end
    local n = tonumber(digits, base)
    if not n then return nil end
    if sign == "-" then n = -n end
    return n
end

local CLICK_DELAY = 0.15

local function sortedClick(entries, status)
    table.sort(entries, function(a, b) return a.value < b.value end)
    status(("clicking %d cells ascending"):format(#entries))
    for i, e in ipairs(entries) do
        fireClick(e.btn)
        status(("%d/%d -> %s"):format(i, #entries, tostring(e.value)))
        task.wait(CLICK_DELAY)
    end
end

local function hoverObject(obj)
    if not obj then return end
    local x, y = 0, 0
    pcall(function()
        local p, s = obj.AbsolutePosition, obj.AbsoluteSize
        x = math.floor(p.X + s.X / 2)
        y = math.floor(p.Y + s.Y / 2)
    end)
    fireSignalSafely(obj.MouseEnter, x, y)
    fireSignalSafely(obj.MouseMoved, x, y)
    fireSignalSafely(obj.InputBegan)
    fireSignalSafely(obj.InputChanged)
end

local function unhoverObject(obj)
    if not obj then return end
    fireSignalSafely(obj.MouseLeave, 0, 0)
end

local function hoverCell(c)
    if c.slot then
        hoverObject(c.slot)
        for _, ch in ipairs(c.slot:GetChildren()) do
            if ch:IsA("GuiObject") then hoverObject(ch) end
        end
    else
        hoverObject(c.mtb); hoverObject(c.btn)
    end
end

local function unhoverCell(c)
    if c.slot then
        for _, ch in ipairs(c.slot:GetChildren()) do
            if ch:IsA("GuiObject") then unhoverObject(ch) end
        end
        unhoverObject(c.slot)
    else
        unhoverObject(c.mtb); unhoverObject(c.btn)
    end
end

local function focusBox(tb)
    pcall(function() tb:CaptureFocus() end)
    fireSignalSafely(tb.Focused)
end

local function submitBox(tb, value)
    tb.Text = tostring(value)
    fireSignalSafely(tb.FocusLost, true)
    pcall(function() tb:ReleaseFocus(true) end)
end

local function cancelBox(tb)
    fireSignalSafely(tb.FocusLost, false)
    pcall(function() tb:ReleaseFocus(false) end)
end

local function waitForFormula(ff, prev, timeout)
    local deadline = os.clock() + (timeout or 0.4)
    while os.clock() < deadline do
        local cur = getFormulaText(ff)
        if cur ~= "" and cur ~= prev then return cur end
        task.wait(0.03)
    end
    return getFormulaText(ff)
end

local function waitCellSolved(c, timeout)
    local deadline = os.clock() + (timeout or 1.5)
    while os.clock() < deadline do
        if c.btn.Visible and not c.mtb.Visible then return true end
        task.wait(0.05)
    end
    return false
end

local function solveL1(status)
    local container, err = findButtonsContainer()
    if not container then return false, err end
    local list = {}
    for _, slot in ipairs(container:GetChildren()) do
        if slot:IsA("Frame") then
            local btn = slot:FindFirstChildOfClass("TextButton")
            local lbl = slot:FindFirstChildOfClass("TextLabel")
            if btn and btn.Visible and (not lbl or not lbl.Visible) then
                local n = tonumber(btn.Text)
                if n then list[#list + 1] = { btn = btn, value = n } end
            end
        end
    end
    if #list == 0 then return false, "no L1 buttons" end
    sortedClick(list, status)
    return true
end

local function solveL2(status)
    local container, err = findButtonsContainer()
    if not container then return false, err end
    local list = {}
    for _, slot in ipairs(container:GetChildren()) do
        if slot:IsA("Frame") then
            local btn = slot:FindFirstChildOfClass("TextButton")
            if btn and btn.Visible then
                local v = decodeShift(btn.Text)
                if v then list[#list + 1] = { btn = btn, value = v } end
            end
        end
    end
    if #list == 0 then return false, "no L2 shift symbols" end
    sortedClick(list, status)
    return true
end

local function solveL3(status)
    local container, err = findButtonsContainer()
    if not container then return false, err end
    local list = {}
    for _, slot in ipairs(container:GetChildren()) do
        if slot:IsA("Frame") then
            local btn = slot:FindFirstChildOfClass("TextButton")
            if btn and btn.Visible then
                local v = parseBased(btn.Text)
                if v then list[#list + 1] = { btn = btn, value = v } end
            end
        end
    end
    if #list == 0 then return false, "no L3 base format" end
    sortedClick(list, status)
    return true
end

local function solveL4(status)
    if type(loadstring) ~= "function" and type(load) ~= "function" then
        return false, "no loadstring"
    end
    local sf, err = findScreenFrame()
    if not sf then return false, err end
    local container = sf:FindFirstChild("Buttons")
    if not container then return false, "Buttons not found" end
    local ff = findFormulaFrame(sf)
    if not ff then return false, "FormulaFrame not found" end

    local cells = {}
    for _, slot in ipairs(container:GetChildren()) do
        if slot:IsA("Frame") then
            local mtb = slot:FindFirstChild("MathTextBox")
            local btn = slot:FindFirstChildOfClass("TextButton")
            if mtb and btn then
                cells[#cells + 1] = { slot = slot, mtb = mtb, btn = btn }
            end
        end
    end
    if #cells == 0 then return false, "no MathTextBox cells" end

    local lastHovered

    local function isPending(c) return c.mtb.Visible and not c.btn.Visible end
    local function countPending()
        local n = 0
        for _, c in ipairs(cells) do if isPending(c) then n = n + 1 end end
        return n
    end

    local function resetHover()
        if lastHovered then unhoverCell(lastHovered); lastHovered = nil end
        hoverObject(sf); unhoverObject(sf)
        task.wait(0.05)
    end

    local function readFormulaForCell(c)
        if lastHovered and lastHovered ~= c then
            unhoverCell(lastHovered)
            task.wait(0.06)
        end
        for attempt = 1, 4 do
            if attempt == 3 then resetHover() end
            hoverCell(c)
            lastHovered = c
            local deadline = os.clock() + 0.5
            local f = ""
            while os.clock() < deadline do
                f = getFormulaText(ff)
                if f ~= "" then break end
                task.wait(0.04)
            end
            if f ~= "" then return f end
            unhoverCell(c)
            task.wait(0.06)
        end
        return getFormulaText(ff)
    end

    local function processCell(i, c)
        if not isPending(c) then return false, "already solved" end
        local formula = readFormulaForCell(c)
        if formula == "" then return false, "no formula" end
        local ans = evaluateMath(formula)
        if not ans then return false, "compute failed: " .. formula end
        local txt = (math.floor(ans) == ans) and string.format("%d", ans) or tostring(ans)
        status(("[L4] %d/%d  %s = %s"):format(i, #cells, formula, txt))
        focusBox(c.mtb)
        task.wait(0.10)
        submitBox(c.mtb, txt)
        local ok = waitCellSolved(c, 1.8)
        task.wait(0.25)
        if ok then return true end
        return false, ("rejected: %s = %s"):format(formula, txt)
    end

    local MAX_PASSES = 8
    local solved = 0
    local lastFails = {}
    for pass = 1, MAX_PASSES do
        if countPending() == 0 then break end
        local progressed = false
        for i, c in ipairs(cells) do
            if isPending(c) then
                local ok, reason = processCell(i, c)
                if ok then
                    solved = solved + 1
                    progressed = true
                    lastFails[i] = nil
                else
                    lastFails[i] = reason
                    cancelBox(c.mtb)
                    if lastHovered then unhoverCell(lastHovered); lastHovered = nil end
                    resetHover()
                end
            end
        end
        local left = countPending()
        status(("[L4] pass %d/%d  solved %d/%d  left %d")
            :format(pass, MAX_PASSES, solved, #cells, left))
        if left == 0 then break end
        if not progressed then resetHover(); task.wait(0.25) else task.wait(0.10) end
    end
    if lastHovered then unhoverCell(lastHovered) end

    local left = countPending()
    if left > 0 then
        local msgs = {}
        for i, c in ipairs(cells) do
            if isPending(c) then
                msgs[#msgs + 1] = ("#%d:%s"):format(i, lastFails[i] or "?")
            end
        end
        return false, ("phase 1 incomplete %d/%d unsolved (%s)")
            :format(left, #cells, table.concat(msgs, ";"))
    end
    status(("[L4] phase 1: %d/%d, settling"):format(solved, #cells))
    task.wait(0.6)

    local readyDeadline = os.clock() + 3
    while os.clock() < readyDeadline do
        local ready = true
        for _, c in ipairs(cells) do
            if not (c.btn.Visible and tonumber(c.btn.Text)) then ready = false; break end
        end
        if ready then break end
        task.wait(0.1)
    end

    local list = {}
    for _, c in ipairs(cells) do
        if c.btn.Visible then
            local n = tonumber(c.btn.Text)
            if n then list[#list + 1] = { btn = c.btn, value = n } end
        end
    end
    if #list ~= #cells then
        return false, ("phase 2: only %d/%d buttons ready"):format(#list, #cells)
    end
    status("[L4] phase 2: clicking")
    sortedClick(list, status)
    return true
end

local function detectLevel()
    local container = findButtonsContainer()
    if not container then return nil end
    local hasMtb, hasShift, hasBased, hasNum = false, false, false, false
    for _, slot in ipairs(container:GetChildren()) do
        if slot:IsA("Frame") then
            local mtb = slot:FindFirstChild("MathTextBox")
            local btn = slot:FindFirstChildOfClass("TextButton")
            if mtb and mtb.Visible then hasMtb = true end
            if btn and btn.Visible then
                local t = btn.Text
                if decodeShift(t) then hasShift = true
                elseif parseBased(t) then hasBased = true
                elseif tonumber(t) then hasNum = true end
            end
        end
    end
    if hasMtb then return "L4" end
    if hasBased then return "L3" end
    if hasShift then return "L2" end
    if hasNum then return "L1" end
    return nil
end

local SOLVERS = { L1 = solveL1, L2 = solveL2, L3 = solveL3, L4 = solveL4 }

local function getGuiParent()
    local lp = game:GetService("Players").LocalPlayer
    if lp then
        local pg = lp:FindFirstChildOfClass("PlayerGui")
        if pg then return pg end
    end
    local h = rawget(getfenv(), "gethui")
    if typeof(h) == "function" then
        local ok, r = pcall(h)
        if ok and r then return r end
    end
    return game:GetService("CoreGui")
end

local guiParent = getGuiParent()
local existing = guiParent:FindFirstChild("HarryPuzzleSolverGui")
if existing then existing:Destroy() end

local screenGui = Instance.new("ScreenGui")
screenGui.Name = "HarryPuzzleSolverGui"
screenGui.ResetOnSpawn = false
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
screenGui.IgnoreGuiInset = true
screenGui.Parent = guiParent

local C = {
    headerBg   = Color3.fromRGB(142, 201, 252),
    border1    = Color3.fromRGB(142, 201, 252),
    border2    = Color3.fromRGB(121, 171, 214),
    panelBg    = Color3.fromRGB(255, 255, 255),
    titleTx    = Color3.fromRGB(12, 50, 85),
    btnBg      = Color3.fromRGB(244, 244, 244),
    btnBgHover = Color3.fromRGB(232, 240, 252),
    btnBorder  = Color3.fromRGB(228, 228, 228),
    btnTx      = Color3.fromRGB(0, 0, 0),
    statusBg   = Color3.fromRGB(252, 252, 252),
    statusTx   = Color3.fromRGB(40, 50, 60),
    hideBg     = Color3.fromRGB(252, 234, 160),
    closeBg    = Color3.fromRGB(252, 118, 118),
    autoOnBg   = Color3.fromRGB(177, 232, 184),
    autoOffBg  = Color3.fromRGB(244, 244, 244),
    stopBg     = Color3.fromRGB(252, 200, 200),
}

local FONT = Enum.Font.SourceSansSemibold
local FONT_REG = Enum.Font.SourceSans

local W, BAR, BODYH = 350, 25, 230
local drag = Instance.new("Frame")
drag.Name = "drag"
drag.BackgroundColor3 = C.headerBg
drag.BorderSizePixel = 0
drag.Size = UDim2.fromOffset(W, BAR)
drag.Position = UDim2.new(0.5, -W/2, 0.4, -(BAR + BODYH)/2)
drag.Active = true
drag.ZIndex = 4
drag.Parent = screenGui

local bg1 = Instance.new("Frame")
bg1.Parent = drag
bg1.BorderSizePixel = 4
bg1.BorderColor3 = C.border1
bg1.BackgroundColor3 = C.panelBg
bg1.Size = UDim2.fromOffset(W, BODYH + 21)
bg1.Position = UDim2.fromOffset(0, 4)
bg1.ZIndex = 0

local bg2 = Instance.new("Frame")
bg2.Parent = bg1
bg2.BorderSizePixel = 5
bg2.BorderColor3 = C.border2
bg2.BackgroundColor3 = C.panelBg
bg2.Size = UDim2.new(1, 0, 1, 0)
bg2.ZIndex = 0

local main = Instance.new("Frame")
main.Parent = drag
main.BackgroundColor3 = C.panelBg
main.BorderSizePixel = 1
main.BorderColor3 = C.border2
main.Size = UDim2.fromOffset(W, BODYH)
main.Position = UDim2.fromOffset(0, BAR)
main.ZIndex = 2

local title = Instance.new("TextLabel")
title.Parent = drag
title.BackgroundTransparency = 1
title.Position = UDim2.fromOffset(8, 0)
title.Size = UDim2.new(1, -90, 1, 0)
title.Font = FONT_REG
title.TextSize = 17
title.TextColor3 = C.titleTx
title.TextXAlignment = Enum.TextXAlignment.Left
title.Text = "HARRY  AUTO-SOLVER"
title.ZIndex = 5

local function makeCornerBtn(name, txt, color, x)
    local b = Instance.new("TextButton")
    b.Name = name
    b.Parent = drag
    b.AutoButtonColor = true
    b.BackgroundColor3 = color
    b.BorderSizePixel = 1
    b.BorderColor3 = C.btnBorder
    b.Size = UDim2.fromOffset(35, 20)
    b.Position = UDim2.fromOffset(x, 2)
    b.Font = FONT_REG
    b.TextSize = 14
    b.TextColor3 = C.btnTx
    b.Text = txt
    b.ZIndex = 5
    return b
end

local hideBtn  = makeCornerBtn("hib", "Hide", C.hideBg,  W - 35 - 35 - 2)
local closeBtn = makeCornerBtn("deb", "Del",  C.closeBg, W - 35 - 2)

local row1 = Instance.new("Frame")
row1.Parent = main
row1.BackgroundTransparency = 1
row1.Size = UDim2.new(1, 0, 0, 30)
row1.Position = UDim2.fromOffset(0, 4)

local row1L = Instance.new("UIListLayout", row1)
row1L.FillDirection = Enum.FillDirection.Horizontal
row1L.HorizontalAlignment = Enum.HorizontalAlignment.Center
row1L.VerticalAlignment = Enum.VerticalAlignment.Center
row1L.Padding = UDim.new(0, 4)
row1L.SortOrder = Enum.SortOrder.LayoutOrder

local function makeTabBtn(parent, label, w, order, bg)
    local b = Instance.new("TextButton")
    b.Parent = parent
    b.LayoutOrder = order
    b.AutoButtonColor = true
    b.BackgroundColor3 = bg or C.btnBg
    b.BorderSizePixel = 1
    b.BorderColor3 = C.btnBorder
    b.Size = UDim2.fromOffset(w, 22)
    b.Font = FONT
    b.TextSize = 14
    b.TextColor3 = C.btnTx
    b.Text = label
    return b
end

local btnL1 = makeTabBtn(row1, "L1", 50, 1)
local btnL2 = makeTabBtn(row1, "L2", 50, 2)
local btnL3 = makeTabBtn(row1, "L3", 50, 3)
local btnL4 = makeTabBtn(row1, "L4", 50, 4)
local btnDetect  = makeTabBtn(row1, "DETECT",  66, 5)
local btnRefresh = makeTabBtn(row1, "REFRESH", 66, 6)

local row2 = Instance.new("Frame")
row2.Parent = main
row2.BackgroundTransparency = 1
row2.Size = UDim2.new(1, 0, 0, 30)
row2.Position = UDim2.fromOffset(0, 38)

local row2L = Instance.new("UIListLayout", row2)
row2L.FillDirection = Enum.FillDirection.Horizontal
row2L.HorizontalAlignment = Enum.HorizontalAlignment.Center
row2L.VerticalAlignment = Enum.VerticalAlignment.Center
row2L.Padding = UDim.new(0, 4)
row2L.SortOrder = Enum.SortOrder.LayoutOrder

local btnAuto = makeTabBtn(row2, "AUTO  OFF", 160, 1, C.autoOffBg)
local btnStop = makeTabBtn(row2, "STOP",      160, 2, C.stopBg)

local statusBox = Instance.new("Frame")
statusBox.Parent = main
statusBox.BackgroundColor3 = C.statusBg
statusBox.BorderSizePixel = 1
statusBox.BorderColor3 = C.btnBorder
statusBox.Size = UDim2.new(1, -16, 0, 130)
statusBox.Position = UDim2.fromOffset(8, 74)

local statusHdr = Instance.new("TextLabel")
statusHdr.Parent = statusBox
statusHdr.BackgroundTransparency = 1
statusHdr.Position = UDim2.fromOffset(6, 2)
statusHdr.Size = UDim2.new(1, -12, 0, 14)
statusHdr.Font = FONT
statusHdr.TextSize = 12
statusHdr.TextColor3 = C.titleTx
statusHdr.TextXAlignment = Enum.TextXAlignment.Left
statusHdr.Text = "STATUS"

local statusLbl = Instance.new("TextLabel")
statusLbl.Parent = statusBox
statusLbl.BackgroundTransparency = 1
statusLbl.Position = UDim2.fromOffset(6, 18)
statusLbl.Size = UDim2.new(1, -12, 1, -22)
statusLbl.Font = FONT_REG
statusLbl.TextSize = 13
statusLbl.TextColor3 = C.statusTx
statusLbl.TextXAlignment = Enum.TextXAlignment.Left
statusLbl.TextYAlignment = Enum.TextYAlignment.Top
statusLbl.TextWrapped = true
statusLbl.Text = "ready"

local function setStatus(s) statusLbl.Text = tostring(s) end

local UIS = game:GetService("UserInputService")
do
    local dragging, dragStart, startPos
    drag.InputBegan:Connect(function(input)
        elevate()
        if input.UserInputType == Enum.UserInputType.MouseButton1
        or input.UserInputType == Enum.UserInputType.Touch then
            dragging = true
            dragStart = input.Position
            startPos = drag.Position
            input.Changed:Connect(function()
                if input.UserInputState == Enum.UserInputState.End then
                    dragging = false
                end
            end)
        end
    end)
    UIS.InputChanged:Connect(function(input)
        if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement
                       or input.UserInputType == Enum.UserInputType.Touch) then
            elevate()
            local delta = input.Position - dragStart
            drag.Position = UDim2.new(
                startPos.X.Scale, startPos.X.Offset + delta.X,
                startPos.Y.Scale, startPos.Y.Offset + delta.Y
            )
        end
    end)
end

closeBtn.MouseButton1Click:Connect(function() elevate(); screenGui:Destroy() end)

local minimized = false
hideBtn.MouseButton1Click:Connect(function()
    elevate()
    minimized = not minimized
    if minimized then
        main.Visible = false; bg1.Visible = false; hideBtn.Text = "Show"
    else
        main.Visible = true; bg1.Visible = true; hideBtn.Text = "Hide"
    end
end)

local running = false
local autoMode = false
local autoThread

local function setAutoBtn(state)
    if state then
        btnAuto.Text = "AUTO  ON"
        btnAuto.BackgroundColor3 = C.autoOnBg
    else
        btnAuto.Text = "AUTO  OFF"
        btnAuto.BackgroundColor3 = C.autoOffBg
    end
end

local function runOnce(name, fn)
    elevate()
    if running then setStatus("busy"); return false end
    running = true
    setStatus(name .. ": start")
    local ok, err, msg = pcall(fn, setStatus)
    running = false
    if not ok then
        setStatus(name .. " error: " .. tostring(err))
        return false
    elseif err == false then
        setStatus(name .. " failed: " .. tostring(msg))
        return false
    else
        setStatus(name .. " done")
        return true
    end
end

local function waitForPlayButton(timeout)
    local deadline = os.clock() + (timeout or 8)
    while os.clock() < deadline do
        if not autoMode then return nil end
        local pb = findPlayButton()
        if pb and isVisibleChain(pb) then return pb end
        task.wait(0.15)
    end
    return findPlayButton()
end

local function waitForLevelReady(timeout)
    local deadline = os.clock() + (timeout or 8)
    while os.clock() < deadline do
        if not autoMode then return nil end
        local lvl = detectLevel()
        if lvl then return lvl end
        task.wait(0.15)
    end
    return detectLevel()
end

local function waitForTransition(prevLvl, timeout)
    local deadline = os.clock() + (timeout or 6)
    while autoMode and os.clock() < deadline do
        local pb = findPlayButton()
        if pb and isVisibleChain(pb) then return "start" end
        local lvl = detectLevel()
        if lvl and lvl ~= prevLvl then return "level", lvl end
        task.wait(0.15)
    end
    return "timeout"
end

local function autoLoop()
    setStatus("auto: scanning")
    local lastLvl
    local blockedLvl, blockedUntil = nil, 0
    while autoMode do
        local pb = findPlayButton()
        if pb and isVisibleChain(pb) then
            elevate()
            fireClick(pb)
            setStatus("auto: START clicked, waiting load")
            lastLvl = nil
            blockedLvl = nil
            local t0 = os.clock()
            while autoMode and os.clock() - t0 < 3.0 do
                local pb2 = findPlayButton()
                if not (pb2 and isVisibleChain(pb2)) then break end
                task.wait(0.1)
            end
            task.wait(1.5)
            local kind, newLvl = waitForTransition(nil, 8)
            if kind == "level" then
                setStatus("auto: " .. newLvl .. " loaded")
                task.wait(0.5)
            end
        else
            local lvl = detectLevel()
            local now = os.clock()
            local isBlocked = lvl and lvl == blockedLvl and now < blockedUntil
            if lvl and lvl ~= lastLvl and not isBlocked then
                elevate()
                running = true
                setStatus("auto: solving " .. lvl)
                local fn = SOLVERS[lvl]
                local ok, err, msg = pcall(fn, setStatus)
                running = false
                if not ok then
                    setStatus("auto: " .. lvl .. " error: " .. tostring(err))
                    local rb = findRegenerateBtn()
                    if rb then
                        fireClick(rb)
                        setStatus("auto: REFRESH after error")
                        task.wait(1.5)
                    else
                        blockedLvl = lvl
                        blockedUntil = os.clock() + 5
                        task.wait(2)
                    end
                elseif err == false then
                    setStatus("auto: " .. lvl .. " failed: " .. tostring(msg))
                    local rb = findRegenerateBtn()
                    if rb then
                        fireClick(rb)
                        setStatus("auto: REFRESH after fail")
                        task.wait(1.5)
                    else
                        blockedLvl = lvl
                        blockedUntil = os.clock() + 5
                        task.wait(2)
                    end
                else
                    setStatus("auto: " .. lvl .. " done")
                    lastLvl = lvl
                    blockedLvl = nil
                    if not autoMode then break end
                    local kind, newLvl = waitForTransition(lvl, 8)
                    if kind == "level" then
                        setStatus("auto: " .. newLvl .. " loaded")
                        lastLvl = nil
                    elseif kind == "start" then
                        setStatus("auto: round done, START visible")
                        lastLvl = nil
                    else
                        setStatus("auto: transition timeout")
                        lastLvl = nil
                    end
                end
            else
                if isBlocked then
                    setStatus(("auto: %s blocked, waiting"):format(lvl))
                elseif lastLvl then
                    setStatus("auto: waiting for next level")
                else
                    setStatus("auto: idle")
                end
                task.wait(0.4)
            end
        end
    end
    setStatus("auto: stopped")
end

btnL1.MouseButton1Click:Connect(function() elevate(); runOnce("L1", solveL1) end)
btnL2.MouseButton1Click:Connect(function() elevate(); runOnce("L2", solveL2) end)
btnL3.MouseButton1Click:Connect(function() elevate(); runOnce("L3", solveL3) end)
btnL4.MouseButton1Click:Connect(function() elevate(); runOnce("L4", solveL4) end)

btnDetect.MouseButton1Click:Connect(function()
    elevate()
    local lvl = detectLevel()
    if lvl then
        runOnce(lvl, SOLVERS[lvl])
    else
        setStatus("DETECT: no level")
    end
end)

btnRefresh.MouseButton1Click:Connect(function()
    elevate()
    local rb = findRegenerateBtn()
    if rb then
        fireClick(rb)
        setStatus("REFRESH: clicked")
    else
        setStatus("REFRESH: button not found")
    end
end)

btnAuto.MouseButton1Click:Connect(function()
    elevate()
    if autoMode then
        autoMode = false
        setAutoBtn(false)
    else
        autoMode = true
        setAutoBtn(true)
        autoThread = task.spawn(autoLoop)
    end
end)

btnStop.MouseButton1Click:Connect(function()
    elevate()
    autoMode = false
    setAutoBtn(false)
    setStatus("stopped")
end)

setStatus("ready - pick a level or AUTO")

Features & Information

Auto solve Harry's puzzle sugma design skid
#eut#puzzle#harry#Everything Upgrade Tree

Community Comments (0)

No comments yet for this script.

More Scripts for Everything Upgrade Tree