--// Auto Enchant GUI - Inventory Scan Method --// Features: --// 1) Multi-unit queue (cycles units list) --// 2) Backup enchants when Dark Aura < Stop Amount --// 3) GUI like mockup + debug log (also prints console) --// 4) Fail-safe idle when Dark Aura is 0/unavailable --// --// Toggle: K --// Unload: M (full unload) --// GUI Scaling (1.0 = normal, 0.9 = 10% smaller, 0.8 = 20% smaller, etc.) local UI_SCALE = 0.5 local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local CoreGui = game:GetService("CoreGui") --======================== -- CONFIG --======================== local TOGGLE_KEY = Enum.KeyCode.K local UNLOAD_KEY = Enum.KeyCode.M -- Loop timing local INVOKE_COOLDOWN = 0.45 -- time to wait after an enchant invoke (lets UI update) local STEP_DELAY = 0.05 -- tiny delay between steps to keep things smooth local IDLE_RECHECK = 1.0 -- how often to check while idling (no aura / all done) -- Match confirmation (prevents “saw Fallen then rerolled it”) local CONFIRM_TIME = 0.70 local CONFIRM_MATCHES = 3 local CONFIRM_SAMPLE_DELAY = 0.12 local DEBUG_DEFAULT = true local MAX_LOG_LINES = 80 --======================== -- Singleton / Cleanup --======================== local SINGLETON_KEY = "_AUTO_ENCHANT_FULL_V1" local env = (getgenv and getgenv()) or _G if env[SINGLETON_KEY] and type(env[SINGLETON_KEY]) == "function" then pcall(env[SINGLETON_KEY]) end local state = { enabled = false, loopToken = 0, conns = {}, gui = nil, manualPos = false, debug = DEBUG_DEFAULT, } local function connect(sig, fn) local c = sig:Connect(fn) table.insert(state.conns, c) return c end local function cleanup() state.enabled = false state.loopToken += 1 for _, c in ipairs(state.conns) do pcall(function() c:Disconnect() end) end state.conns = {} if state.gui then pcall(function() state.gui:Destroy() end) end env[SINGLETON_KEY] = nil print("[AutoEnchant] Unloaded.") end env[SINGLETON_KEY] = cleanup --======================== -- Paths (your UI) --======================== local player = Players.LocalPlayer local main = player:WaitForChild("PlayerGui"):WaitForChild("Main") local unitEnchantFrame = main:WaitForChild("UnitEnchant"):WaitForChild("MainFrame") local unitInventory = main:WaitForChild("UnitInventory") local inventoryFrame = unitInventory:WaitForChild("MainFrame"):WaitForChild("InventoryFrame") local unitScroll = inventoryFrame:WaitForChild("UnitScrollingFrame") local itemsScroll = inventoryFrame:WaitForChild("ItemsScrollingFrame") local darkAuraLabel = itemsScroll:WaitForChild("Dark Aura") :WaitForChild("UnitAmount") -- "x24" local enchantRemote = ReplicatedStorage:WaitForChild("EnchantUnit") -- RemoteFunction --======================== -- Helpers --======================== local function norm(s) return tostring(s or ""):lower():gsub("^%s+", ""):gsub("%s+$", "") end local function splitList(text) -- supports commas and newlines local out = {} text = tostring(text or "") text = text:gsub("\r", "\n") text = text:gsub(",", "\n") for line in text:gmatch("[^\n]+") do local v = line:gsub("^%s+", ""):gsub("%s+$", "") if v ~= "" then table.insert(out, v) end end return out end local function parseXAmount(txt) -- "x24" -> 24 txt = tostring(txt or ""):gsub(",", "") local n = txt:match("^x(%d+)$") or txt:match("x(%d+)") return tonumber(n) or 0 end local function getDarkAura() return parseXAmount(darkAuraLabel.Text) end local function enchantTextToValue(txt) -- "Enchant Label" == no enchant if not txt then return nil end local t = tostring(txt):gsub("^%s+", ""):gsub("%s+$", "") if t == "" then return nil end if t == "Enchant Label" then return nil end return t end local function anyMatches(current, list) local cur = norm(current) for _, v in ipairs(list or {}) do if cur == norm(v) then return true, v end end return false, nil end local function unionLists(a, b) local out = {} for _, v in ipairs(a or {}) do table.insert(out, v) end for _, v in ipairs(b or {}) do table.insert(out, v) end return out end -- Find enchant TextLabel inside a unit container (descendant scan) local function findEnchantLabel(unitContainer) for _, d in ipairs(unitContainer:GetDescendants()) do if d.Name == "Enchant" and d:IsA("TextLabel") then return d end end return nil end local function getUnitEnchant(unitName) local unitContainer = unitScroll:FindFirstChild(unitName) if not unitContainer then return nil, "MISSING" end local lbl = findEnchantLabel(unitContainer) if not lbl then return nil, "NO_LABEL" end return enchantTextToValue(lbl.Text), "OK" end local function confirmTarget(unitName, acceptedTargets) local matches = 0 local t0 = os.clock() while os.clock() - t0 < CONFIRM_TIME do local cur, status = getUnitEnchant(unitName) if status == "MISSING" then return false, "MISSING" end if cur then local ok = anyMatches(cur, acceptedTargets) if ok then matches += 1 if matches >= CONFIRM_MATCHES then return true, cur end end end task.wait(CONFIRM_SAMPLE_DELAY) end return false, "NOT_STABLE" end --======================== -- GUI (mockup style + debug log) --======================== local gui = Instance.new("ScreenGui") gui.Name = "AutoEnchantGUI" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.Parent = player:FindFirstChild("PlayerGui") or CoreGui state.gui = gui local panel = Instance.new("Frame") panel.Size = UDim2.fromOffset(1080, 420) -- base size (unscaled) panel.BackgroundColor3 = Color3.fromRGB(10,10,10) panel.BorderSizePixel = 0 panel.Active = true panel.Parent = gui Instance.new("UICorner", panel).CornerRadius = UDim.new(0, 26) -- >>> ADD THIS (group-scale everything like Adobe Express) local scaler = Instance.new("UIScale") scaler.Name = "PanelScaler" scaler.Scale = UI_SCALE scaler.Parent = panel local border = Instance.new("UIStroke", panel) border.Thickness = 6 border.Color = Color3.fromRGB(255, 90, 80) local title = Instance.new("TextLabel") title.BackgroundTransparency = 1 title.Size = UDim2.new(1, -30, 0, 40) title.Position = UDim2.fromOffset(15, 10) title.Font = Enum.Font.GothamMedium title.TextSize = 22 title.TextColor3 = Color3.fromRGB(220,220,220) title.Text = "Auto Enchant GUI - Inventory Scan Method" title.TextXAlignment = Enum.TextXAlignment.Center title.Parent = panel local function mkBox(y, h, placeholder) local tb = Instance.new("TextBox") tb.Size = UDim2.new(1, -60, 0, h) tb.Position = UDim2.fromOffset(30, y) tb.BackgroundColor3 = Color3.fromRGB(85,85,85) tb.TextColor3 = Color3.fromRGB(235,235,235) tb.PlaceholderColor3 = Color3.fromRGB(210,210,210) tb.PlaceholderText = placeholder tb.ClearTextOnFocus = false tb.Font = Enum.Font.Gotham tb.TextSize = 16 tb.TextWrapped = true tb.Text = "" tb.Parent = panel Instance.new("UICorner", tb).CornerRadius = UDim.new(0, 14) return tb end local unitsBox = mkBox(60, 54, "Units to enchant. (comma or newline separated)") unitsBox.Text = "Frost Queen, Moon Watcher, Golden Signal" local leftBox = Instance.new("TextBox") leftBox.Size = UDim2.new(0.5, -40, 0, 46) leftBox.Position = UDim2.fromOffset(30, 122) leftBox.BackgroundColor3 = Color3.fromRGB(85,85,85) leftBox.TextColor3 = Color3.fromRGB(235,235,235) leftBox.PlaceholderText = "Dark Aura Stop Amount:" leftBox.ClearTextOnFocus = false leftBox.Font = Enum.Font.Gotham leftBox.TextSize = 16 leftBox.Text = "25" leftBox.Parent = panel Instance.new("UICorner", leftBox).CornerRadius = UDim.new(0, 14) local backupBox = Instance.new("TextBox") backupBox.Size = UDim2.new(0.5, -40, 0, 46) backupBox.Position = UDim2.fromOffset(30 + (panel.Size.X.Offset/2), 122) -- right side backupBox.BackgroundColor3 = Color3.fromRGB(85,85,85) backupBox.TextColor3 = Color3.fromRGB(235,235,235) backupBox.PlaceholderText = "Enchant Backups. (comma/newline)" backupBox.ClearTextOnFocus = false backupBox.Font = Enum.Font.Gotham backupBox.TextSize = 16 backupBox.Text = "Damage, Range, Speed" backupBox.Parent = panel Instance.new("UICorner", backupBox).CornerRadius = UDim.new(0, 14) local mainEnchantsBox = mkBox(178, 54, "Main Enchants (comma/newline)") mainEnchantsBox.Text = "Golden, Fallen" local toggleBtn = Instance.new("TextButton") toggleBtn.Size = UDim2.new(1, -60, 0, 68) toggleBtn.Position = UDim2.fromOffset(30, 238) toggleBtn.BackgroundColor3 = Color3.fromRGB(190, 0, 0) toggleBtn.TextColor3 = Color3.fromRGB(255,255,255) toggleBtn.Font = Enum.Font.GothamBlack toggleBtn.TextSize = 44 toggleBtn.Text = "Auto Enchant OFF." toggleBtn.Parent = panel Instance.new("UICorner", toggleBtn).CornerRadius = UDim.new(0, 16) local logBox = Instance.new("TextBox") logBox.Size = UDim2.new(1, -60, 0, 70) logBox.Position = UDim2.fromOffset(30, 312) logBox.BackgroundColor3 = Color3.fromRGB(20,20,20) logBox.TextColor3 = Color3.fromRGB(210,210,210) logBox.Font = Enum.Font.Code logBox.TextSize = 12 logBox.TextXAlignment = Enum.TextXAlignment.Left logBox.TextYAlignment = Enum.TextYAlignment.Top logBox.ClearTextOnFocus = false logBox.TextEditable = false logBox.MultiLine = true logBox.Text = "" logBox.Parent = panel Instance.new("UICorner", logBox).CornerRadius = UDim.new(0, 10) local logPad = Instance.new("UIPadding", logBox) logPad.PaddingLeft = UDim.new(0, 8) logPad.PaddingTop = UDim.new(0, 6) logPad.PaddingRight = UDim.new(0, 8) logPad.PaddingBottom = UDim.new(0, 6) local logLines = {} local function log(msg) local line = ("[%s] %s"):format(os.date("%H:%M:%S"), tostring(msg)) table.insert(logLines, line) if #logLines > MAX_LOG_LINES then table.remove(logLines, 1) end logBox.Text = table.concat(logLines, "\n") logBox.CursorPosition = #logBox.Text + 1 print("[AutoEnchant]", msg) end local function setEnabled(on) state.enabled = on if on then toggleBtn.BackgroundColor3 = Color3.fromRGB(0, 150, 70) toggleBtn.Text = "Auto Enchant ON." else toggleBtn.BackgroundColor3 = Color3.fromRGB(190, 0, 0) toggleBtn.Text = "Auto Enchant OFF." end end -- draggable + auto-anchor under enchant UI until dragged do local dragging = false local dragStart, startPos connect(panel.InputBegan, function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true state.manualPos = true dragStart = input.Position startPos = panel.Position end end) connect(UserInputService.InputChanged, function(input) if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then local delta = input.Position - dragStart panel.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) end end) connect(UserInputService.InputEnded, function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end end) end -- show only when enchant UI open, and auto-place if not manually moved connect(RunService.RenderStepped, function() panel.Visible = unitEnchantFrame.Visible if not panel.Visible then return end if not state.manualPos then local p, s = unitEnchantFrame.AbsolutePosition, unitEnchantFrame.AbsoluteSize panel.Position = UDim2.fromOffset(p.X - 10, p.Y + s.Y + 16) end end) --======================== -- Main loop --======================== local function getStopAmount() local n = tonumber(leftBox.Text) if not n then return 0 end if n < 0 then n = 0 end return n end local function getLists() local units = splitList(unitsBox.Text) local mainTargets = splitList(mainEnchantsBox.Text) local backups = splitList(backupBox.Text) return units, mainTargets, backups end local function getAcceptedTargets(aura, stopAmt, mainTargets, backups) if aura < stopAmt then return unionLists(mainTargets, backups), "BACKUP MODE" end return mainTargets, "MAIN MODE" end local function allUnitsSatisfied(units, acceptedTargets) for _, u in ipairs(units) do local cur, status = getUnitEnchant(u) if status == "MISSING" then -- missing units are ignored (not a failure) else local ok = false if cur then ok = anyMatches(cur, acceptedTargets) end if not ok then return false end end end return true end local function startLoop() state.loopToken += 1 local myToken = state.loopToken task.spawn(function() log("Loop started. (K toggle, M unload)") while state.enabled and state.loopToken == myToken do -- If enchant UI closed, just wait (keeps enabled) if not unitEnchantFrame.Visible then log("Enchant UI closed -> waiting...") task.wait(IDLE_RECHECK) continue end local units, mainTargets, backups = getLists() if #units == 0 then log("No units listed. Add units to enchant.") task.wait(IDLE_RECHECK) continue end if #mainTargets == 0 and #backups == 0 then log("No enchants listed. Add main/backups.") task.wait(IDLE_RECHECK) continue end local aura = getDarkAura() local stopAmt = getStopAmount() if aura <= 0 then log(("Dark Aura=%d -> idle until it returns..."):format(aura)) task.wait(IDLE_RECHECK) continue end local acceptedTargets, mode = getAcceptedTargets(aura, stopAmt, mainTargets, backups) log(("Mode=%s | DarkAura=%d | Stop=%d | Units=%d"):format(mode, aura, stopAmt, #units)) -- If everyone already has an accepted enchant, idle but stay enabled if allUnitsSatisfied(units, acceptedTargets) then log("All listed units already match accepted enchants -> standing by...") task.wait(IDLE_RECHECK) continue end -- Cycle units for _, unitName in ipairs(units) do if not (state.enabled and state.loopToken == myToken) then break end local cur, status = getUnitEnchant(unitName) if status == "MISSING" then log(("Unit '%s' missing from UnitScrollingFrame -> skipping"):format(unitName)) task.wait(STEP_DELAY) continue end if cur then local ok = anyMatches(cur, acceptedTargets) if ok then log(("%s already good: %s -> next unit"):format(unitName, cur)) task.wait(STEP_DELAY) continue else log(("%s current=%s (not accepted) -> rolling..."):format(unitName, cur)) end else log(("%s current=(none) -> rolling..."):format(unitName)) end -- Invoke enchant local ok, res = pcall(function() return enchantRemote:InvokeServer(unitName) end) if not ok then log(("Invoke error on %s: %s"):format(unitName, tostring(res))) task.wait(0.8) continue end -- Let UI update task.wait(INVOKE_COOLDOWN) -- Re-check + confirm if hit local after, _ = getUnitEnchant(unitName) if after then local hit = anyMatches(after, acceptedTargets) if hit then log(("%s saw target '%s' -> confirming..."):format(unitName, after)) local confirmed, final = confirmTarget(unitName, acceptedTargets) if confirmed then log(("%s confirmed '%s' -> locking it in, moving on"):format(unitName, final)) else log(("%s match not stable yet -> continuing later"):format(unitName)) end else log(("%s rolled -> now=%s"):format(unitName, after)) end else log(("%s rolled -> still shows (none)"):format(unitName)) end task.wait(STEP_DELAY) end end log("Loop exited.") end) end --======================== -- Controls --======================== connect(toggleBtn.MouseButton1Click, function() setEnabled(not state.enabled) if state.enabled then startLoop() else log("Toggled OFF.") end end) connect(UserInputService.InputBegan, function(input, gp) if gp then return end if input.KeyCode == TOGGLE_KEY then setEnabled(not state.enabled) if state.enabled then startLoop() else log("Toggled OFF.") end elseif input.KeyCode == UNLOAD_KEY then cleanup() end end) -- Init setEnabled(false) log("Ready. Enter units + enchants. Toggle with K. Unload with M.")