Auto Enchant
Key Required

Auto Enchant

[⚡EVENT] Idle DefenseMediorceExploiterMediorceExploiter 1.5K views 20 executesUpdated Jan 23, 2026
5.0/ 5(1 votes)
10100% Positive
Lua Script•557 lines (16117 chars)
--// 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.")

Features & Information

Auto enchant units. (Must have unit in inventory & not placed down, also keep inventory open.) Generated by ChatGPT 5.2
#OP#auto

Community Comments (2)

PngclaimPngclaimJan 23, 2026

Wow

ravencosmos98ravencosmos98Jan 23, 2026

jehe

More Scripts for [⚡EVENT] Idle Defense