+1 Loot to Forge Scripts 2026 — (NO KEY) Auto Farm

Published Updated 81 views
  • 10 scripts
  • 7 NO KEY
  • 3 KEY SYSTEM
  • 10 mobile

Browse 10 +1 Loot to Forge scripts in this collection. 7 offer NO KEY access; 3 use a key system. 10 list mobile support.

Reviewed by RobScript Team

Tested: October 15, 2026, on PC with Potassium. We didn’t test on mobile; mobile support on the cards is what developers list.

If you want one script to play +1 Loot to Forge for you, start with Selux. It was the only hub where we watched the full loop work: it farmed stages and the Frozen Tower, forged gear stronger than ours and equipped it. The rest do one job each, and two of them failed at forging.

Best +1 Loot to Forge Scripts by Task

SeluxNo Key
Everything at once: farming, tower, forge and auto-equip. Open source.
View script
Apel HubKey System
Race rolls that stop on your target race. Its feature list has no Forge.
View script
World Boss: Ouroboros and SerenityHub didn’t teleport to the boss. Vyral and BP Hub list boss fighting, but they need a key and we haven’t tested them yet. Want to read the code first? Selux and Autofarm OpenSource are open source.

What Each Script Did in Our Test

What worked and failed for us, kept apart from what developers only list.

ScriptWorkedFailed or limitedUntested or missing
Stages, Frozen Tower, forge and auto-equip
—
Untested: enchant, enhance, race rolls. Not in its list: World Boss
Ore collection with the rarity filter, return and repeat
Forge: Forge remote is unavailable. World Boss teleport
Untested: Frozen Tower, enhance
Drop magnet; Kill Aura in the tower; two spawner items after a rejoin
Rest of the spawner list unconfirmed
Untested: Forge, Super Loot boss hunting
Infinite HP; one-shots on mobs with numeric HP
A goblin with percentage HP survived
Not in its list: farming, Forge, tower
Teleport, ore pickup, return, next stage
Couldn’t clear stage 6 with a weak weapon
Not in its code: Forge, tower, World Boss
—
Forge crafted nothing. World Boss teleport
Untested: main Auto Farm, tower
—
—
No results yet
Apel Hub (key)
Farm, priority order, race-roll stop on Yeti
—
Not in its list: Forge, tower, World Boss
Vyral (key)
—
—
Not tested, including World Boss
BP Hub (key)
—
—
Not tested, including World Boss

What Failed and What It Means

Forge errors
Ouroboros stopped with “Forge remote is unavailable”, and SerenityHub’s Forge crafted nothing. The message means the hub couldn’t reach the game’s forge, which often happens after a game update. Forge with Selux or by hand until the developer updates the hub.
Weak weapon, stuck farm
A farm-only script can’t clear stages your damage can’t. Autofarm OpenSource couldn’t clear stage 6 with our weapon. Upgrade your gear before you leave it running.

NO KEY Scripts

Ordered by how much of the game each one handled in our test, not by a score.

Selux
Selux script preview

Selux

Developer
Seltonmt
Updated
Updated
Working
NO KEY PC MOBILE OPEN SOURCE

In our test, whenever Selux could forge something stronger than what we were wearing, it forged it and equipped it, for weapons, armor and hats. The code is open source: read the game file from the Source link before you run it.

  • Auto Farm Stages
  • Auto Forge
  • Auto Equip Best Gear
  • +24 more
Limitation: We didn’t separately check enchanting, enhancing, race rolls or auto-selling. The Frozen Tower round count isn’t confirmed.
Copies 20 Discord Source
Details

Functions

  • Auto Farm Stages
  • Auto Forge
  • Auto Equip Best Gear
  • Stage Depth Selection
  • Auto Train
  • Training Interval
  • Auto Rebirth
  • Auto Buy Upgrades
  • Prioritize Bag Upgrades
  • Auto Upgrade Ore Bag
  • Auto Upgrade Train Boost
  • Auto Upgrade Luck
  • Auto Forge Armor & Hats
  • Auto Sell Weaker Gear
  • Frozen Tower Auto Farm
  • Tower Ticket Reserve
  • Auto Claim Daily Tower Ticket
  • Auto Claim Online Gifts
  • Auto Claim Index Rewards
  • Auto Enchant Worn Gear
  • Preferred Enchant Element
  • Auto Enhance Worn Gear
  • Enhance Level Limit
  • Auto Complete Enhance Quests
  • Auto Roll Races
  • Auto Equip Best Race
  • Anti-AFK
Access
NO KEY
Tags
PC MOBILE OPEN SOURCE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://raw.githubusercontent.com/seltonmt012/sel01-rbx/main/loader.lua"))()
Ouroboros
Ouroboros script preview

Ouroboros

Developer
Ouroboros Hub
Updated
Updated
Working
NO KEY PC MOBILE

In our test, Auto Collect Ore picked up loot in dungeon runs, went back to the lobby after each stage and started again. The rarity filter worked: pick the rarities to keep, or leave it empty to take everything. Auto World Boss tracks the spawn, which took about 15 minutes for us, but it didn’t teleport us when the boss appeared.

  • Auto Farm Dungeon
  • Auto Collect Ore
  • Ore Rarity Filter
  • +42 more
Limitation: Forge failed with “Forge remote is unavailable”. Use it for ore, not for forging.
Copies 5 Discord
Details

Functions

  • Auto Farm Dungeon
  • Auto Collect Ore
  • Ore Rarity Filter
  • Stage Selection
  • Force Kill Stage Enemies
  • Auto Farm Tower
  • Start Round Selection
  • Start at Highest Unlocked Round
  • Force Kill Tower Enemies
  • Claim Daily Tower Ticket
  • Auto Forge
  • Target Gear Selection
  • Forge Ore Rarity Filter
  • Spend Best Ore First
  • Keep Ore Reserve
  • Auto Enhance
  • Enhance Selected Gear Types
  • Enhance Equipped Gear Only
  • Max Enhance Level
  • Protection Scroll for Risky Enhancements
  • Auto World Boss
  • World Boss Reward Card Selection
  • Auto Rebirth
  • Auto Buy Upgrades
  • Upgrade Selection
  • Auto Train
  • Training Area Selection
  • Auto Click
  • Auto Sell Items
  • Item Type Filter
  • Sell Rarity Filter
  • Keep Copies Per Item
  • Auto Claim Online Rewards
  • Auto Claim Index Rewards
  • WalkSpeed
  • Infinite Jump
  • Noclip
  • Instant Proximity Prompt
  • Fly
  • Fly Speed
  • Anti-AFK / No Gameplay Paused
  • Auto Reconnect on Kick
  • Disable 3D Rendering
  • FPS Boost
  • Hide UI on Start
Access
NO KEY
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://raw.githubusercontent.com/joustingmatch/Ouroboros/main/loader.lua"))()
Ouroboros Collect tab with Auto Collect Ore and the Ore Rarities filter from Common to Mythic
Ouroboros: Auto Collect Ore with the Ore Rarities filter.
Ouroboros World Boss tab with Auto World Boss on and the status Waiting for the boss to spawn
Ouroboros: Auto World Boss waiting for the spawn.
VenxzCSK
VenxzCSK script preview

VenxzCSK

Developer
VenxzCSK
Updated
Updated
Working
NO KEY PC MOBILE

In our test, Auto Drop Magnet grabbed ore the moment it dropped, and in the Frozen Tower Kill Aura hit the enemies on each stage. Auto Evacuate on Full Backpack is in the menu, but we didn’t test it on its own. At first only the Ember Stone spawner seemed to work. After a rejoin, Abyssal Doom and Crimson Calamity, two of the items the spawner lists, appeared in the inventory. We can’t say why they showed up late or whether the rest of the list works.

  • Auto Drop Magnet
  • Kill Aura
  • Premium Item Spawner
  • +28 more
Limitation: Our tester found the UI cramped, and it can’t be resized from the corner. Only some spawner items appeared, after a rejoin.
Copies 5 Discord
Details

Functions

  • Auto Drop Magnet
  • Kill Aura
  • Premium Item Spawner
  • Loot: Safe Zone Drop Magnet, Player Drop Magnet, Ultra Prompt, Instant Drop Collection
  • Combat: Dungeon and Stage Instant Kill, God Mode, Safe Combat Flight with adjustable height
  • Spawner items: Apocalypse, Tri-Wyrm, Cataclysm and Void Overlord sets; Apex Ore; Tier III Rune; Ember Stone (single and bulk)
  • Smart Auto Farm engine with dungeon priority, Stage Blitz and auto train when idle
  • Auto Forge and Auto Upgrade management, real-time farming stats
  • Evacuation: Auto Evacuate on Full Backpack, on Low HP and to the Safe Zone
  • Auto Sell: inventory, trash gear, ores, enchant stones; Instant Sell All
  • Ore and gear rarity filters, Inventory Protection
  • Dungeons: Auto Dungeon Farming, Auto Dungeon Ticket Claim, Custom Dungeon Round
  • Stages: Auto Stage Farming, Max Stage Detection, Auto Stage Climbing, Smart Stage Retreat
  • Super Loot Boss Hunter: tier selection (Legendary, Eternal, Secret), boss detection, scan and teleport
  • Training: Auto Power Training, best zone and multiplier selection, remote-only training, VIP training modes
  • Auto Sword Power Clicker, adjustable training speed, Auto Attribute Upgrade, All-in-One Upgrade
  • Auto Rebirth (script and native)
  • Forge: weapons, armor and hats; Smart Auto Forge; farming and forging at the same time
  • Forge settings: ore quality selection, high- or low-grade ore priority, minimum ore, Instant Forge
  • Equipment: Auto Equip Best, Auto Enhance, Auto Enchant, Unequip All, Remove Enchants
  • Class: Auto Class Rolling with target class, star selection, Smart Class Roll Stop, auto lock and equip
  • Auto Skill Cell Rolling and Class Data Scanner
  • Potions: damage, training, coin and luck; Auto Pet Egg Hatching
  • Rewards: offline, online, dungeon, quest and daily ticket claims; code and batch promo code redemption
  • Teleports: Safe Zone, Training Area, Dungeon Entrance, saved position
  • Server: Rejoin, Auto Reconnect, Low-Population Server Hop, copy Job ID
  • Discord webhook: rare drops, hourly reports, rebirth milestones, boss spawns, live status
  • WalkSpeed, JumpPower, Infinite Jump, Noclip, Anti-AFK
  • Low CPU/GPU mode, FPS optimization, automatic error recovery
  • Named configs with save, load and auto save; automatic game data discovery
  • English and Thai UI, themes, glass transparency, session stats, Destroy UI
Access
NO KEY
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://nexzan-hub-only.netlify.app/api/raw/2kNN7jB3cg"))()
Destine Scripts
Destine Scripts script preview

Destine Scripts

Developer
Destine Scripts
Updated
Updated
Working
NO KEY PC MOBILE

In our test, Infinite HP kept us from dying, and the health bar showed nan/100. Kill Aura is rough, but it made our attacks one-shot mobs whose HP is shown as a number. Use Destine to clear dungeons above your power.

  • Infinite Health
  • Kill Aura
Limitation: Combat only. A goblin with HP shown in percent survived the one-shot.
Copies 3
Details

Functions

  • Infinite Health
  • Kill Aura
Access
NO KEY
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://raw.githubusercontent.com/lavalledestineluis25-afk/Destinehub.-1LootToForge.Official/refs/heads/main/DestineHub", true))()
Destine Scripts menu with Kill Aura and Infinite HP enabled and the health bar showing nan/100
Destine Scripts: Infinite HP on, health reads nan/100.
Destine Scripts Kill Aura hits showing -nan damage on dungeon mobs whose health bars drop to 0
Destine Scripts: Kill Aura hits show -nan, and mobs with numeric HP drop to 0.
Autofarm OpenSource
Autofarm OpenSource script preview

Autofarm OpenSource

Developer
PewPewT
Updated
Updated
Working
NO KEY PC MOBILE OPEN SOURCE

In our test, the script teleported into the dungeon, held the character above the enemies and picked up dropped ore through the ProximityPrompt. The ore landed in the backpack, and after each stage it went back to base and continued. Check your inventory for what you collected, not the counter in the menu. From the code on this card: it carries 4 ores per trip by default (Max carry goes up to 20), skips a stage if enemies survive 30 seconds, and restarts from your starting stage if you die. The return button is clicked at a fixed screen point, with a local teleport as a fallback.

  • Auto Farm
  • Auto Loot
  • Return to Spawn
  • +9 more
Limitation: Progress depends on your weapon: ours couldn’t clear stage 6. It can’t repeat one stage: it always moves on and returns to your starting stage after stage 27.
Copies 1
Details

Functions

  • Auto Farm
  • Auto Loot
  • Return to Spawn
  • Teleports through dungeon stages and hovers above enemies
  • Picks up dropped ore through the ProximityPrompt
  • Returns after looting, then continues to the next stage
  • Starting stage selection
  • Max carry setting
  • Flight height and fly responsiveness sliders
  • Teleport tab for every stage and spawn
  • Manual tools: loot one ore, force advance stage, reset to start stage
  • Status tab and console logs
Access
NO KEY
Tags
PC MOBILE OPEN SOURCE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
-- Auto Farm + Teleport + Manual — for the fighting game
-- Flight only while fighting enemies; smooth exponential; slider for height
local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local VIM = game:GetService("VirtualInputManager")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local LocalPlayer = Players.LocalPlayer

-- ============================================================
-- SPAWN RETURN BUTTON
-- ============================================================
local BACK_X = 1279
local BACK_Y = 138

-- ============================================================
-- STAGES (1-27) — x, y, z
-- ============================================================
local STAGES = {
    [1]  = {-1, 10, -131},
    [2]  = {1, 10, -232},
    [3]  = {0, 10, -342},
    [4]  = {-1, 10, -454},
    [5]  = {-1, 10, -537},
    [6]  = {-1, 10, -650},
    [7]  = {-1, 10, -750},
    [8]  = {-1, 10, -870},
    [9]  = {-1, 10, -985},
    [10] = {-1, 10, -1093},
    [11] = {-1, 10, -1208},
    [12] = {-1, 10, -1306},
    [13] = {2, 10, -1415},
    [14] = {1, 10, -1536},
    [15] = {1, 10, -1640},
    [16] = {1, 10, -1750},
    [17] = {1, 10, -1850},
    [18] = {1, 10, -1950},
    [19] = {1, 10, -2063},
    [20] = {1, 10, -2180},
    [21] = {-1, 10, -2285},
    [22] = {-1, 10, -2380},
    [23] = {-1, 10, -2500},
    [24] = {-1, 10, -2615},
    [25] = {-1, 10, -2720},
    [26] = {-1, 10, -2830},
    [27] = {-1, 10, -2925},
}
local SPAWN = {1, 10, 5}
local MAX_STAGE = 27

-- ============================================================
-- CONFIG
-- ============================================================
local Config = {
    MaxCarry          = 4,
    EnemiesGoneChecks = 4,
    CheckInterval     = 0.4,
    KillTimeout       = 30,
    LootRetries       = 3,
    Log               = true,
    AutoLoot          = true,
    ReturnToSpawn     = true,
    HoldDuration      = 0.8,
    PromptExtraHold   = 0.15,
    SpawnWait         = 1.0,

    -- Flight
    FlightHeight      = 15,    -- studs above the stage Y to hover
    FlyGain           = 6,     -- responsiveness; lower = smoother
    FlyDeadzone       = 0.4,
}

-- ============================================================
-- STATE
-- ============================================================
local Farm = {
    running       = false,
    state         = "idle",   -- idle | toStage | waiting | looting | toSpawn
    currentStage  = 1,
    startStage    = 1,
    oresCarried   = 0,
    zeroStreak    = 0,
    stageStartedAt= 0,
    lastLog       = "",
    killsTotal    = 0,
    stagesPassed  = 0,
    deaths        = 0,
    loopCount     = 0,
    lastLootMethod= "—",
    spawnCalls    = 0,
    hoverTarget   = nil,      -- Vector3 target for flight
}

local function log(m)
    if Config.Log then print("[Farm] " .. m) end
    Farm.lastLog = m
end

-- ============================================================
-- HELPERS
-- ============================================================
local function getChar()
    return LocalPlayer.Character
end

local function getRoot()
    local c = getChar()
    return c and c:FindFirstChild("HumanoidRootPart")
end

local function getHumanoid()
    local c = getChar()
    return c and c:FindFirstChildOfClass("Humanoid")
end

local function isAlive()
    local hum = getHumanoid()
    return hum and hum.Health > 0
end

local function tpTo(x, y, z)
    local root = getRoot()
    if not root then return false end
    local ok = pcall(function()
        root.CFrame = CFrame.new(x, y, z)
    end)
    return ok
end

local function tpToVector(v)
    return tpTo(v[1], v[2], v[3])
end

-- ============================================================
-- FLIGHT
-- ============================================================
local function setHoverTarget(x, y, z)
    Farm.hoverTarget = Vector3.new(x, y + Config.FlightHeight, z)
end

local function clearHoverTarget()
    Farm.hoverTarget = nil
end

local function zeroVelocity(root)
    pcall(function() root.AssemblyLinearVelocity = Vector3.zero end)
    pcall(function() root.AssemblyAngularVelocity = Vector3.zero end)
    pcall(function() root.Velocity = Vector3.zero end)
    pcall(function() root.RotVelocity = Vector3.zero end)
end

RunService.Heartbeat:Connect(function(dt)
    if not Farm.running then return end
    if Farm.state ~= "waiting" then return end
    local target = Farm.hoverTarget
    if not target then return end
    local root = getRoot()
    if not root then return end

    local current = root.Position
    local delta = target - current
    local dist = delta.Magnitude

    if dist < Config.FlyDeadzone then
        zeroVelocity(root)
        return
    end

    local alpha = 1 - math.exp(-Config.FlyGain * dt)
    local newPos = current:Lerp(target, alpha)
    local rot = root.CFrame - root.CFrame.Position

    pcall(function()
        root.CFrame = CFrame.new(newPos) * rot
        zeroVelocity(root)
    end)
end)

-- ============================================================
-- SILENT CLICK
-- ============================================================
local function silentClickAt(x, y)
    local ok = pcall(function()
        VIM:SendMouseButtonEvent(math.floor(x), math.floor(y), 0, true,  game, 0)
        task.wait(0.04)
        VIM:SendMouseButtonEvent(math.floor(x), math.floor(y), 0, false, game, 0)
    end)
    return ok
end

-- ============================================================
-- RETURN TO SPAWN
-- ============================================================
local function returnToSpawnAndReset()
    if not Config.ReturnToSpawn then return end
    clearHoverTarget()

    local ok = silentClickAt(BACK_X, BACK_Y)
    Farm.spawnCalls += 1
    if ok then
        log(("Clicked Return at (%d, %d) — waiting %.1fs"):format(
            BACK_X, BACK_Y, Config.SpawnWait))
    else
        log("Return click failed — local TP fallback.")
        tpToVector(SPAWN)
    end

    task.wait(Config.SpawnWait)

    local root = getRoot()
    if root then
        local d = (root.Position - Vector3.new(SPAWN[1], SPAWN[2], SPAWN[3])).Magnitude
        if d > 25 then
            log(("Not at spawn (%.0f studs). Local TP fallback."):format(d))
            tpToVector(SPAWN)
            task.wait(0.4)
        end
    end
end

-- ============================================================
-- ENEMY / ORE DETECTION
-- ============================================================
local function getEnemyFolder()
    return Workspace:FindFirstChild("EnemyFolder")
end

local function isIgnoredEnemy(obj)
    return obj.Name:sub(1, 3) == "SSS"
end

local function countKillableEnemies()
    local folder = getEnemyFolder()
    if not folder then return 0 end
    local n = 0
    for _, obj in ipairs(folder:GetChildren()) do
        if not isIgnoredEnemy(obj) then n += 1 end
    end
    return n
end

local function getOreCache()
    return Workspace:FindFirstChild("OreCache")
end

local function findOreObjects()
    local cache = getOreCache()
    if not cache then return {} end
    local list = {}
    for _, obj in ipairs(cache:GetDescendants()) do
        local num = obj.Name:match("^Ore_(%d+)")
        if num then
            table.insert(list, { obj = obj, num = tonumber(num) })
        end
    end
    if #list == 0 then
        for _, obj in ipairs(cache:GetChildren()) do
            local num = obj.Name:match("^Ore_(%d+)")
            if num then
                table.insert(list, { obj = obj, num = tonumber(num) })
            end
        end
    end
    return list
end

local function getHighestOre()
    local all = findOreObjects()
    if #all == 0 then return nil, 0, 0 end
    local best = all[1]
    for _, entry in ipairs(all) do
        if entry.num > best.num then best = entry end
    end
    return best.obj, best.num, #all
end

local function orePosition(ore)
    if not ore or not ore.Parent then return nil end
    if ore:IsA("BasePart") then return ore.Position end
    if ore:IsA("Model") then
        local pp = ore.PrimaryPart
            or ore:FindFirstChildWhichIsA("BasePart", true)
        return pp and pp.Position or nil
    end
    if ore:IsA("Attachment") then return ore.WorldPosition end
    local bp = ore:FindFirstChildWhichIsA("BasePart", true)
    if bp then return bp.Position end
    return nil
end

local function findPromptFor(ore)
    if not ore then return nil end
    local node = ore
    for _ = 1, 4 do
        if not node then break end
        local p = node:FindFirstChildOfClass("ProximityPrompt")
        if p then return p end
        for _, d in ipairs(node:GetDescendants()) do
            if d:IsA("ProximityPrompt") then return d end
        end
        node = node.Parent
    end
    local myRoot = getRoot()
    if not myRoot then return nil end
    local best, bestDist = nil, 12
    for _, d in ipairs(Workspace:GetDescendants()) do
        if d:IsA("ProximityPrompt") and d.Parent then
            local pos = orePosition(d.Parent)
                or (d.Parent:IsA("BasePart") and d.Parent.Position)
            if pos and (pos - myRoot.Position).Magnitude < bestDist then
                best, bestDist = d, (pos - myRoot.Position).Magnitude
            end
        end
    end
    return best
end

local function pressKey(key, duration)
    duration = duration or 0.3
    pcall(function()
        VIM:SendKeyEvent(true, key, false, game)
        task.wait(duration)
        VIM:SendKeyEvent(false, key, false, game)
    end)
end

local function holdE(duration)
    pressKey(Enum.KeyCode.E, duration or Config.HoldDuration)
end

-- ============================================================
-- LOOT ONE ORE — snap-teleport, NO flight
-- ============================================================
local function tryLootOneOre()
    Farm.lastLootMethod = "starting…"

    local ore, num, total = getHighestOre()
    if not ore then
        Farm.lastLootMethod = "no ore found in OreCache"
        return false
    end
    log(("Loot: highest = %s (index %d, %d ores total)")
        :format(ore:GetFullName(), num, total))

    local pos = orePosition(ore)
    if not pos then
        Farm.lastLootMethod = "ore has no position"
        return false
    end

    tpTo(pos.X, pos.Y + 3, pos.Z)
    task.wait(0.2)

    local root = getRoot()
    if root then
        local dist = (root.Position - pos).Magnitude
        if dist > 20 then
            Farm.lastLootMethod = "tp didn't stick"
            return false
        end
    else
        Farm.lastLootMethod = "no root"
        return false
    end

    local prompt = findPromptFor(ore)
    if prompt then
        local wasEnabled = prompt.Enabled
        if not wasEnabled then
            pcall(function() prompt.Enabled = true end)
            task.wait(0.05)
        end
        local holdTime = math.max(prompt.HoldDuration or 0.5, 0.3)
            + Config.PromptExtraHold
        local ok2 = pcall(function()
            prompt:InputHoldBegin()
            task.wait(holdTime)
            prompt:InputHoldEnd()
        end)
        if not wasEnabled then
            pcall(function() prompt.Enabled = false end)
        end
        task.wait(0.15)
        if ok2 then
            Farm.lastLootMethod = ("prompt(%.2fs)"):format(holdTime)
            return true
        end
    end

    holdE(Config.HoldDuration)
    task.wait(0.25)
    Farm.lastLootMethod = ("vim(%.2fs)"):format(Config.HoldDuration)
    return true
end

local function handleLooting()
    if Farm.oresCarried >= Config.MaxCarry then
        Farm.state = "toSpawn"
        return
    end

    local ore = getHighestOre()
    if not ore then
        log(("No more ores (carried %d)."):format(Farm.oresCarried))
        Farm.state = "toSpawn"
        return
    end

    local got = false
    for _ = 1, Config.LootRetries do
        if tryLootOneOre() then got = true break end
    end

    if got then
        Farm.oresCarried += 1
        log(("Looted ore %d/%d via %s"):format(
            Farm.oresCarried, Config.MaxCarry, Farm.lastLootMethod))
    else
        log("Could not pick up any ore. Moving on.")
        Farm.state = "toSpawn"
    end
end

-- ============================================================
-- FARM LOOP
-- ============================================================
local function goToStage(stage)
    local pos = STAGES[stage]
    if not pos then return false end
    Farm.currentStage = stage
    Farm.stageStartedAt = os.clock()
    Farm.zeroStreak = 0

    setHoverTarget(pos[1], pos[2], pos[3])
    local h = Farm.hoverTarget
    tpTo(h.X, h.Y, h.Z)

    log(("Stage %d — snapped to (%.0f, %.0f, %.0f), flying to hold at Y=%.0f")
        :format(stage, pos[1], pos[2], pos[3], h.Y))
    return true
end

local function advanceStage()
    Farm.stagesPassed += 1
    if Farm.currentStage >= MAX_STAGE then
        log("Reached last stage. Looping back to start stage.")
        Farm.loopCount += 1
        goToStage(Farm.startStage)
    else
        goToStage(Farm.currentStage + 1)
    end
end

local function farmTick()
    if not Farm.running then return end

    if not isAlive() then
        Farm.deaths += 1
        log(("Died! Restarting from stage %d."):format(Farm.startStage))
        Farm.oresCarried = 0
        Farm.state = "toStage"
        Farm.currentStage = Farm.startStage - 1
        task.wait(1)
        goToStage(Farm.startStage)
        return
    end

    if Farm.state == "toStage" then
        if Farm.currentStage == 0 then Farm.currentStage = Farm.startStage end
        goToStage(Farm.currentStage)
        Farm.state = "waiting"

    elseif Farm.state == "waiting" then
        local n = countKillableEnemies()
        if n == 0 then
            Farm.zeroStreak += 1
            if Farm.zeroStreak >= Config.EnemiesGoneChecks then
                log(("Stage %d cleared (%d checks)."):format(
                    Farm.currentStage, Farm.zeroStreak))
                Farm.killsTotal += 1
                Farm.oresCarried = 0
                clearHoverTarget()
                if Config.AutoLoot then
                    Farm.state = "looting"
                else
                    Farm.state = "toSpawn"
                end
            end
        else
            Farm.zeroStreak = 0
        end

        if os.clock() - Farm.stageStartedAt > Config.KillTimeout then
            log(("Stage %d timeout — moving on."):format(Farm.currentStage))
            clearHoverTarget()
            Farm.state = "toSpawn"
        end

    elseif Farm.state == "looting" then
        handleLooting()

    elseif Farm.state == "toSpawn" then
        returnToSpawnAndReset()
        advanceStage()
        Farm.state = "waiting"

    elseif Farm.state == "done" then
        Farm.running = false
    end
end

task.spawn(function()
    while true do
        if Farm.running then
            local ok, err = pcall(farmTick)
            if not ok then
                warn("[Farm] tick error: " .. tostring(err))
            end
            task.wait(Config.CheckInterval)
        else
            task.wait(0.15)
        end
    end
end)

-- ============================================================
-- SIGNAL AUTOTRAIN
-- ============================================================
local function signalAutoTrainOff(off)
    if getgenv then
        getgenv().AutoTrain_ForceOff = off and true or false
    end
end

-- ============================================================
-- GUI
-- ============================================================
local gui = Instance.new("ScreenGui")
gui.Name = "AutoFarm"
gui.ResetOnSpawn = false
gui.ZIndexBehavior = Enum.ZIndexBehavior.Global
gui.Parent = game:GetService("CoreGui")

local frame = Instance.new("Frame")
frame.Size = UDim2.new(0, 400, 0, 520)
frame.Position = UDim2.new(0.5, -200, 0.5, -260)
frame.BackgroundColor3 = Color3.fromRGB(22, 26, 34)
frame.BorderSizePixel = 0
frame.Active = true
frame.Draggable = true
frame.ZIndex = 10
frame.Parent = gui
Instance.new("UICorner", frame).CornerRadius = UDim.new(0, 10)

local title = Instance.new("TextLabel")
title.Size = UDim2.new(1, 0, 0, 30)
title.BackgroundColor3 = Color3.fromRGB(35, 45, 60)
title.Text = "Auto Farm"
title.TextColor3 = Color3.fromRGB(210, 230, 255)
title.Font = Enum.Font.GothamBold
title.TextSize = 14
title.ZIndex = 11
title.Parent = frame
Instance.new("UICorner", title).CornerRadius = UDim.new(0, 10)

local close = Instance.new("TextButton")
close.Size = UDim2.new(0, 22, 0, 22)
close.Position = UDim2.new(1, -26, 0, 4)
close.BackgroundColor3 = Color3.fromRGB(140, 50, 50)
close.Text = "X"
close.TextColor3 = Color3.fromRGB(255, 255, 255)
close.Font = Enum.Font.GothamBold
close.TextSize = 12
close.ZIndex = 12
close.Parent = frame
Instance.new("UICorner", close).CornerRadius = UDim.new(0, 6)
close.MouseButton1Click:Connect(function()
    Farm.running = false
    clearHoverTarget()
    signalAutoTrainOff(false)
    gui:Destroy()
end)

local tabBar = Instance.new("Frame")
tabBar.Size = UDim2.new(1, -20, 0, 30)
tabBar.Position = UDim2.new(0, 10, 0, 36)
tabBar.BackgroundColor3 = Color3.fromRGB(32, 40, 52)
tabBar.BorderSizePixel = 0
tabBar.ZIndex = 11
tabBar.Parent = frame
Instance.new("UICorner", tabBar).CornerRadius = UDim.new(0, 6)

local function mkTabBtn(text, xScale)
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(0.25, -2, 1, -4)
    b.Position = UDim2.new(xScale, 2, 0, 2)
    b.BackgroundColor3 = Color3.fromRGB(45, 55, 70)
    b.TextColor3 = Color3.fromRGB(180, 200, 220)
    b.Font = Enum.Font.GothamBold
    b.TextSize = 11
    b.Text = text
    b.ZIndex = 12
    b.Parent = tabBar
    Instance.new("UICorner", b).CornerRadius = UDim.new(0, 5)
    return b
end

local farmTabBtn = mkTabBtn("Farm", 0)
local tpTabBtn   = mkTabBtn("Teleport", 0.25)
local manualTabBtn = mkTabBtn("Manual", 0.5)
local statusTabBtn = mkTabBtn("Status", 0.75)

-- ============================================================
-- SLIDER HELPER
-- ============================================================
local function mkSlider(parent, y, minVal, maxVal, initial, label, precision, onChange)
    local holder = Instance.new("Frame")
    holder.Size = UDim2.new(0.9, 0, 0, 40)
    holder.Position = UDim2.new(0.05, 0, 0, y)
    holder.BackgroundTransparency = 1
    holder.ZIndex = 11
    holder.Parent = parent

    local lbl = Instance.new("TextLabel")
    lbl.Size = UDim2.new(1, 0, 0, 14)
    lbl.BackgroundTransparency = 1
    lbl.Text = label .. ": " .. string.format("%." .. precision .. "f", initial)
    lbl.TextColor3 = Color3.fromRGB(190, 210, 230)
    lbl.Font = Enum.Font.Gotham
    lbl.TextSize = 11
    lbl.TextXAlignment = Enum.TextXAlignment.Left
    lbl.ZIndex = 12
    lbl.Parent = holder

    local track = Instance.new("TextButton")
    track.Size = UDim2.new(1, 0, 0, 12)
    track.Position = UDim2.new(0, 0, 0, 22)
    track.BackgroundColor3 = Color3.fromRGB(38, 44, 54)
    track.Text = ""
    track.AutoButtonColor = false
    track.BorderSizePixel = 0
    track.ZIndex = 12
    track.Parent = holder
    Instance.new("UICorner", track).CornerRadius = UDim.new(1, 0)

    local pct0 = (initial - minVal) / (maxVal - minVal)

    local fill = Instance.new("Frame")
    fill.Size = UDim2.new(pct0, 0, 1, 0)
    fill.BackgroundColor3 = Color3.fromRGB(70, 130, 200)
    fill.BorderSizePixel = 0
    fill.ZIndex = 13
    fill.Parent = track
    Instance.new("UICorner", fill).CornerRadius = UDim.new(1, 0)

    local handle = Instance.new("Frame")
    handle.Size = UDim2.new(0, 16, 0, 16)
    handle.Position = UDim2.new(pct0, -8, 0.5, -8)
    handle.BackgroundColor3 = Color3.fromRGB(220, 230, 255)
    handle.BorderSizePixel = 0
    handle.ZIndex = 14
    handle.Parent = track
    Instance.new("UICorner", handle).CornerRadius = UDim.new(1, 0)

    local value = initial
    local function setValue(v, silent)
        v = math.clamp(v, minVal, maxVal)
        value = v
        local pct = (v - minVal) / (maxVal - minVal)
        fill.Size = UDim2.new(pct, 0, 1, 0)
        handle.Position = UDim2.new(pct, -8, 0.5, -8)
        lbl.Text = label .. ": " .. string.format("%." .. precision .. "f", v)
        if not silent then onChange(v) end
    end

    local dragging = false
    track.InputBegan:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1
           or input.UserInputType == Enum.UserInputType.Touch then
            dragging = true
            local rel = (input.Position.X - track.AbsolutePosition.X) / track.AbsoluteSize.X
            setValue(minVal + rel * (maxVal - minVal))
        end
    end)
    UIS.InputChanged:Connect(function(input)
        if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement
                         or input.UserInputType == Enum.UserInputType.Touch) then
            local rel = (input.Position.X - track.AbsolutePosition.X) / track.AbsoluteSize.X
            setValue(minVal + rel * (maxVal - minVal))
        end
    end)
    UIS.InputEnded:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1
           or input.UserInputType == Enum.UserInputType.Touch then
            dragging = false
        end
    end)

    setValue(initial, true)
    return holder, setValue
end

-- ============================================================
-- FARM TAB
-- ============================================================
local farmTab = Instance.new("Frame")
farmTab.Size = UDim2.new(1, 0, 1, -76)
farmTab.Position = UDim2.new(0, 0, 0, 76)
farmTab.BackgroundTransparency = 1
farmTab.ZIndex = 11
farmTab.Parent = frame

local toggle = Instance.new("TextButton")
toggle.Size = UDim2.new(0.9, 0, 0, 44)
toggle.Position = UDim2.new(0.05, 0, 0, 6)
toggle.BackgroundColor3 = Color3.fromRGB(70, 75, 85)
toggle.TextColor3 = Color3.fromRGB(255, 255, 255)
toggle.Font = Enum.Font.GothamBold
toggle.TextSize = 15
toggle.Text = "Auto Farm: OFF"
toggle.ZIndex = 11
toggle.Parent = farmTab
Instance.new("UICorner", toggle).CornerRadius = UDim.new(0, 6)

toggle.MouseButton1Click:Connect(function()
    Farm.running = not Farm.running
    toggle.BackgroundColor3 = Farm.running
        and Color3.fromRGB(60, 140, 60) or Color3.fromRGB(70, 75, 85)
    toggle.Text = "Auto Farm: " .. (Farm.running and "ON" or "OFF")

    if Farm.running then
        signalAutoTrainOff(true)
        Farm.currentStage = Farm.startStage
        Farm.oresCarried = 0
        Farm.zeroStreak = 0
        Farm.state = "toStage"
        log(("Farm started at stage %d"):format(Farm.startStage))
    else
        signalAutoTrainOff(false)
        clearHoverTarget()
        log("Farm stopped.")
    end
end)

local stageHdr = Instance.new("TextLabel")
stageHdr.Size = UDim2.new(0.9, 0, 0, 16)
stageHdr.Position = UDim2.new(0.05, 0, 0, 60)
stageHdr.BackgroundTransparency = 1
stageHdr.Text = "Starting stage: 1"
stageHdr.TextColor3 = Color3.fromRGB(190, 210, 230)
stageHdr.Font = Enum.Font.Gotham
stageHdr.TextSize = 11
stageHdr.TextXAlignment = Enum.TextXAlignment.Left
stageHdr.ZIndex = 11
stageHdr.Parent = farmTab

local stageMinus = Instance.new("TextButton")
stageMinus.Size = UDim2.new(0, 40, 0, 26)
stageMinus.Position = UDim2.new(0.05, 0, 0, 80)
stageMinus.BackgroundColor3 = Color3.fromRGB(60, 100, 160)
stageMinus.TextColor3 = Color3.fromRGB(255, 255, 255)
stageMinus.Font = Enum.Font.GothamBold
stageMinus.TextSize = 12
stageMinus.Text = "-1"
stageMinus.ZIndex = 11
stageMinus.Parent = farmTab
Instance.new("UICorner", stageMinus).CornerRadius = UDim.new(0, 5)
stageMinus.MouseButton1Click:Connect(function()
    Farm.startStage = math.max(1, Farm.startStage - 1)
    stageHdr.Text = "Starting stage: " .. Farm.startStage
end)

local stagePlus = Instance.new("TextButton")
stagePlus.Size = UDim2.new(0, 40, 0, 26)
stagePlus.Position = UDim2.new(0.85, 0, 0, 80)
stagePlus.BackgroundColor3 = Color3.fromRGB(60, 100, 160)
stagePlus.TextColor3 = Color3.fromRGB(255, 255, 255)
stagePlus.Font = Enum.Font.GothamBold
stagePlus.TextSize = 12
stagePlus.Text = "+1"
stagePlus.ZIndex = 11
stagePlus.Parent = farmTab
Instance.new("UICorner", stagePlus).CornerRadius = UDim.new(0, 5)
stagePlus.MouseButton1Click:Connect(function()
    Farm.startStage = math.min(MAX_STAGE, Farm.startStage + 1)
    stageHdr.Text = "Starting stage: " .. Farm.startStage
end)

local dropdownBtn = Instance.new("TextButton")
dropdownBtn.Size = UDim2.new(0.5, 0, 0, 26)
dropdownBtn.Position = UDim2.new(0.25, 0, 0, 80)
dropdownBtn.BackgroundColor3 = Color3.fromRGB(60, 90, 130)
dropdownBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
dropdownBtn.Font = Enum.Font.GothamBold
dropdownBtn.TextSize = 11
dropdownBtn.Text = "Pick stage…"
dropdownBtn.ZIndex = 11
dropdownBtn.Parent = farmTab
Instance.new("UICorner", dropdownBtn).CornerRadius = UDim.new(0, 5)

local dropdown = Instance.new("Frame")
dropdown.Size = UDim2.new(0.5, 0, 0, 200)
dropdown.Position = UDim2.new(0.25, 0, 0, 108)
dropdown.BackgroundColor3 = Color3.fromRGB(30, 38, 50)
dropdown.BorderSizePixel = 0
dropdown.Visible = false
dropdown.ZIndex = 20
dropdown.Parent = farmTab
Instance.new("UICorner", dropdown).CornerRadius = UDim.new(0, 6)

local ddScroll = Instance.new("ScrollingFrame")
ddScroll.Size = UDim2.new(1, -6, 1, -6)
ddScroll.Position = UDim2.new(0, 3, 0, 3)
ddScroll.BackgroundTransparency = 1
ddScroll.BorderSizePixel = 0
ddScroll.ScrollBarThickness = 4
ddScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
ddScroll.ZIndex = 21
ddScroll.Parent = dropdown
local ddLayout = Instance.new("UIListLayout")
ddLayout.Padding = UDim.new(0, 2)
ddLayout.Parent = ddScroll

for s = 1, MAX_STAGE do
    local btn = Instance.new("TextButton")
    btn.Size = UDim2.new(1, -4, 0, 22)
    btn.BackgroundColor3 = Color3.fromRGB(45, 55, 70)
    btn.TextColor3 = Color3.fromRGB(220, 230, 240)
    btn.Font = Enum.Font.Gotham
    btn.TextSize = 11
    btn.Text = "Stage " .. s
    btn.ZIndex = 22
    btn.Parent = ddScroll
    Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 4)
    btn.MouseButton1Click:Connect(function()
        Farm.startStage = s
        stageHdr.Text = "Starting stage: " .. s
        dropdown.Visible = false
    end)
end
ddScroll.CanvasSize = UDim2.new(0, 0, 0, ddLayout.AbsoluteContentSize.Y + 6)

dropdownBtn.MouseButton1Click:Connect(function()
    dropdown.Visible = not dropdown.Visible
end)

local function mkOption(text, y, key, default)
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(0.9, 0, 0, 30)
    b.Position = UDim2.new(0.05, 0, 0, y)
    b.BackgroundColor3 = Config[key] and Color3.fromRGB(60, 140, 60) or Color3.fromRGB(70, 75, 85)
    b.TextColor3 = Color3.fromRGB(255, 255, 255)
    b.Font = Enum.Font.GothamBold
    b.TextSize = 11
    b.Text = text .. ": " .. (Config[key] and "ON" or "OFF")
    b.ZIndex = 11
    b.Parent = farmTab
    Instance.new("UICorner", b).CornerRadius = UDim.new(0, 6)
    b.MouseButton1Click:Connect(function()
        Config[key] = not Config[key]
        b.BackgroundColor3 = Config[key] and Color3.fromRGB(60, 140, 60) or Color3.fromRGB(70, 75, 85)
        b.Text = text .. ": " .. (Config[key] and "ON" or "OFF")
    end)
end

mkOption("Auto Loot", 130, "AutoLoot", true)
mkOption("Return to Spawn", 166, "ReturnToSpawn", true)

-- Max carry
local carryHdr = Instance.new("TextLabel")
carryHdr.Size = UDim2.new(0.9, 0, 0, 16)
carryHdr.Position = UDim2.new(0.05, 0, 0, 206)
carryHdr.BackgroundTransparency = 1
carryHdr.Text = "Max carry: " .. Config.MaxCarry
carryHdr.TextColor3 = Color3.fromRGB(190, 210, 230)
carryHdr.Font = Enum.Font.Gotham
carryHdr.TextSize = 11
carryHdr.TextXAlignment = Enum.TextXAlignment.Left
carryHdr.ZIndex = 11
carryHdr.Parent = farmTab

local carryMinus = Instance.new("TextButton")
carryMinus.Size = UDim2.new(0, 40, 0, 24)
carryMinus.Position = UDim2.new(0.05, 0, 0, 224)
carryMinus.BackgroundColor3 = Color3.fromRGB(60, 100, 160)
carryMinus.TextColor3 = Color3.fromRGB(255, 255, 255)
carryMinus.Font = Enum.Font.GothamBold
carryMinus.TextSize = 11
carryMinus.Text = "-1"
carryMinus.ZIndex = 11
carryMinus.Parent = farmTab
Instance.new("UICorner", carryMinus).CornerRadius = UDim.new(0, 5)
carryMinus.MouseButton1Click:Connect(function()
    Config.MaxCarry = math.max(1, Config.MaxCarry - 1)
    carryHdr.Text = "Max carry: " .. Config.MaxCarry
end)

local carryPlus = Instance.new("TextButton")
carryPlus.Size = UDim2.new(0, 40, 0, 24)
carryPlus.Position = UDim2.new(0.85, 0, 0, 224)
carryPlus.BackgroundColor3 = Color3.fromRGB(60, 100, 160)
carryPlus.TextColor3 = Color3.fromRGB(255, 255, 255)
carryPlus.Font = Enum.Font.GothamBold
carryPlus.TextSize = 11
carryPlus.Text = "+1"
carryPlus.ZIndex = 11
carryPlus.Parent = farmTab
Instance.new("UICorner", carryPlus).CornerRadius = UDim.new(0, 5)
carryPlus.MouseButton1Click:Connect(function()
    Config.MaxCarry = math.min(20, Config.MaxCarry + 1)
    carryHdr.Text = "Max carry: " .. Config.MaxCarry
end)

-- FLIGHT HEIGHT SLIDER (replaces old fly controls)
mkSlider(farmTab, 258, 0, 60, Config.FlightHeight,
    "Flight height (studs above stage)", 0,
    function(v) Config.FlightHeight = v end)

-- Info panel
local infoPanel = Instance.new("TextLabel")
infoPanel.Size = UDim2.new(0.9, 0, 0, 130)
infoPanel.Position = UDim2.new(0.05, 0, 0, 306)
infoPanel.BackgroundColor3 = Color3.fromRGB(18, 22, 28)
infoPanel.TextColor3 = Color3.fromRGB(180, 210, 220)
infoPanel.Font = Enum.Font.Code
infoPanel.TextSize = 10
infoPanel.TextXAlignment = Enum.TextXAlignment.Left
infoPanel.TextYAlignment = Enum.TextYAlignment.Top
infoPanel.TextWrapped = true
infoPanel.Text = "  Ready."
infoPanel.ZIndex = 11
infoPanel.Parent = farmTab
Instance.new("UICorner", infoPanel).CornerRadius = UDim.new(0, 6)

-- ============================================================
-- TELEPORT TAB
-- ============================================================
local tpTab = Instance.new("Frame")
tpTab.Size = UDim2.new(1, 0, 1, -76)
tpTab.Position = UDim2.new(0, 0, 0, 76)
tpTab.BackgroundTransparency = 1
tpTab.Visible = false
tpTab.ZIndex = 11
tpTab.Parent = frame

local tpScroll = Instance.new("ScrollingFrame")
tpScroll.Size = UDim2.new(0.94, 0, 0.85, 0)
tpScroll.Position = UDim2.new(0.03, 0, 0, 6)
tpScroll.BackgroundColor3 = Color3.fromRGB(28, 34, 44)
tpScroll.BorderSizePixel = 0
tpScroll.ScrollBarThickness = 6
tpScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
tpScroll.ZIndex = 11
tpScroll.Parent = tpTab
Instance.new("UICorner", tpScroll).CornerRadius = UDim.new(0, 6)
local tpLayout = Instance.new("UIListLayout")
tpLayout.Padding = UDim.new(0, 3)
tpLayout.Parent = tpScroll

for s = 1, MAX_STAGE do
    local pos = STAGES[s]
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(1, -6, 0, 28)
    b.BackgroundColor3 = Color3.fromRGB(45, 60, 80)
    b.TextColor3 = Color3.fromRGB(220, 230, 240)
    b.Font = Enum.Font.GothamBold
    b.TextSize = 11
    b.Text = ("Stage %d  (%.0f, %.0f, %.0f)"):format(s, pos[1], pos[2], pos[3])
    b.ZIndex = 12
    b.Parent = tpScroll
    Instance.new("UICorner", b).CornerRadius = UDim.new(0, 4)
    b.MouseButton1Click:Connect(function()
        tpToVector(pos)
        log(("Teleported to stage %d"):format(s))
    end)
end
tpScroll.CanvasSize = UDim2.new(0, 0, 0, tpLayout.AbsoluteContentSize.Y + 8)

local spawnBtn = Instance.new("TextButton")
spawnBtn.Size = UDim2.new(0.94, 0, 0, 32)
spawnBtn.Position = UDim2.new(0.03, 0, 1, -42)
spawnBtn.BackgroundColor3 = Color3.fromRGB(60, 100, 160)
spawnBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
spawnBtn.Font = Enum.Font.GothamBold
spawnBtn.TextSize = 12
spawnBtn.Text = ("Silent Click Return (%d, %d)"):format(BACK_X, BACK_Y)
spawnBtn.ZIndex = 11
spawnBtn.Parent = tpTab
Instance.new("UICorner", spawnBtn).CornerRadius = UDim.new(0, 6)
spawnBtn.MouseButton1Click:Connect(function()
    task.spawn(returnToSpawnAndReset)
end)

local localTpBtn = Instance.new("TextButton")
localTpBtn.Size = UDim2.new(0.94, 0, 0, 24)
localTpBtn.Position = UDim2.new(0.03, 0, 1, -78)
localTpBtn.BackgroundColor3 = Color3.fromRGB(70, 75, 85)
localTpBtn.TextColor3 = Color3.fromRGB(220, 220, 240)
localTpBtn.Font = Enum.Font.GothamBold
localTpBtn.TextSize = 11
localTpBtn.Text = ("Local TP to Spawn (%.0f, %.0f, %.0f)"):format(SPAWN[1], SPAWN[2], SPAWN[3])
localTpBtn.ZIndex = 11
localTpBtn.Parent = tpTab
Instance.new("UICorner", localTpBtn).CornerRadius = UDim.new(0, 6)
localTpBtn.MouseButton1Click:Connect(function()
    tpToVector(SPAWN)
    log("Local TP to spawn.")
end)

-- ============================================================
-- MANUAL TAB
-- ============================================================
local manualTab = Instance.new("Frame")
manualTab.Size = UDim2.new(1, 0, 1, -76)
manualTab.Position = UDim2.new(0, 0, 0, 76)
manualTab.BackgroundTransparency = 1
manualTab.Visible = false
manualTab.ZIndex = 11
manualTab.Parent = frame

local function mkBtn(text, y, color, onClick)
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(0.9, 0, 0, 30)
    b.Position = UDim2.new(0.05, 0, 0, y)
    b.BackgroundColor3 = color
    b.TextColor3 = Color3.fromRGB(255, 255, 255)
    b.Font = Enum.Font.GothamBold
    b.TextSize = 12
    b.Text = text
    b.ZIndex = 11
    b.Parent = manualTab
    Instance.new("UICorner", b).CornerRadius = UDim.new(0, 6)
    b.MouseButton1Click:Connect(onClick)
    return b
end

mkBtn(("Silent click Return (%d, %d)"):format(BACK_X, BACK_Y), 6,
    Color3.fromRGB(60, 100, 160), function()
    silentClickAt(BACK_X, BACK_Y)
    log("Sent silent click to Return.")
end)

mkBtn("Clear hover target", 42, Color3.fromRGB(140, 80, 40), function()
    clearHoverTarget()
    log("Hover target cleared.")
end)

mkBtn("Count killable enemies", 78, Color3.fromRGB(60, 100, 160), function()
    local n = countKillableEnemies()
    log(("Killable enemies in EnemyFolder: %d"):format(n))
end)

mkBtn("Find highest ore (detail)", 114, Color3.fromRGB(60, 100, 160), function()
    local cache = getOreCache()
    if not cache then
        log("No Workspace.OreCache found.")
        return
    end
    log(("OreCache children: %d"):format(#cache:GetChildren()))
    local all = findOreObjects()
    log(("Ore_ matches found (recursive): %d"):format(#all))
    for i = 1, math.min(10, #all) do
        local e = all[i]
        local p = orePosition(e.obj)
        log(("  [%d] %s  class=%s  index=%d  pos=%s"):format(
            i, e.obj:GetFullName(), e.obj.ClassName, e.num,
            p and ("(%.1f, %.1f, %.1f)"):format(p.X, p.Y, p.Z) or "nil"))
    end
end)

mkBtn("Loot one ore now", 150, Color3.fromRGB(120, 60, 160), function()
    task.spawn(function()
        local ok = tryLootOneOre()
        log(ok and ("Looted one ore via " .. Farm.lastLootMethod)
                or "Loot attempt failed.")
    end)
end)

mkBtn("Force advance stage", 186, Color3.fromRGB(120, 60, 160), function()
    advanceStage()
end)

mkBtn("Reset to start stage", 222, Color3.fromRGB(140, 80, 40), function()
    Farm.currentStage = Farm.startStage
    goToStage(Farm.startStage)
    Farm.state = "waiting"
    log(("Reset to stage %d"):format(Farm.startStage))
end)

mkBtn("Kill Auto Train (safety)", 258, Color3.fromRGB(140, 50, 50), function()
    signalAutoTrainOff(true)
    log("AutoTrain force-off signaled.")
end)

-- FLY RESPONSIVENESS (moved here from Farm tab)
mkSlider(manualTab, 296, 1, 20, Config.FlyGain,
    "Fly responsiveness (lower = smoother)", 1,
    function(v) Config.FlyGain = v end)

-- ============================================================
-- STATUS TAB
-- ============================================================
local statusTab = Instance.new("Frame")
statusTab.Size = UDim2.new(1, 0, 1, -76)
statusTab.Position = UDim2.new(0, 0, 0, 76)
statusTab.BackgroundTransparency = 1
statusTab.Visible = false
statusTab.ZIndex = 11
statusTab.Parent = frame

local statusBox = Instance.new("TextLabel")
statusBox.Size = UDim2.new(0.94, 0, 0.85, 0)
statusBox.Position = UDim2.new(0.03, 0, 0, 6)
statusBox.BackgroundColor3 = Color3.fromRGB(18, 22, 28)
statusBox.TextColor3 = Color3.fromRGB(180, 210, 220)
statusBox.Font = Enum.Font.Code
statusBox.TextSize = 11
statusBox.TextXAlignment = Enum.TextXAlignment.Left
statusBox.TextYAlignment = Enum.TextYAlignment.Top
statusBox.TextWrapped = true
statusBox.ZIndex = 11
statusBox.Parent = statusTab
Instance.new("UICorner", statusBox).CornerRadius = UDim.new(0, 6)

local lastLogBox = Instance.new("TextLabel")
lastLogBox.Size = UDim2.new(0.94, 0, 0, 50)
lastLogBox.Position = UDim2.new(0.03, 0, 1, -56)
lastLogBox.BackgroundColor3 = Color3.fromRGB(30, 40, 30)
lastLogBox.TextColor3 = Color3.fromRGB(200, 240, 200)
lastLogBox.Font = Enum.Font.Code
lastLogBox.TextSize = 10
lastLogBox.TextXAlignment = Enum.TextXAlignment.Left
lastLogBox.TextYAlignment = Enum.TextYAlignment.Top
lastLogBox.TextWrapped = true
lastLogBox.Text = "  No logs yet."
lastLogBox.ZIndex = 11
lastLogBox.Parent = statusTab
Instance.new("UICorner", lastLogBox).CornerRadius = UDim.new(0, 6)

-- ============================================================
-- TAB SWITCHING
-- ============================================================
local tabButtons = {
    farm = farmTabBtn, tp = tpTabBtn, manual = manualTabBtn, status = statusTabBtn,
}
local tabFrames = {
    farm = farmTab, tp = tpTab, manual = manualTab, status = statusTab,
}

local function switchTab(name)
    for k, b in pairs(tabButtons) do
        local active = (k == name)
        b.BackgroundColor3 = active and Color3.fromRGB(70, 130, 200) or Color3.fromRGB(45, 55, 70)
        b.TextColor3 = active and Color3.fromRGB(255, 255, 255) or Color3.fromRGB(180, 200, 220)
    end
    for k, f in pairs(tabFrames) do
        f.Visible = (k == name)
    end
end

farmTabBtn.MouseButton1Click:Connect(function() switchTab("farm") end)
tpTabBtn.MouseButton1Click:Connect(function() switchTab("tp") end)
manualTabBtn.MouseButton1Click:Connect(function() switchTab("manual") end)
statusTabBtn.MouseButton1Click:Connect(function() switchTab("status") end)

-- ============================================================
-- UI UPDATE LOOP
-- ============================================================
task.spawn(function()
    while gui.Parent do
        local hum = getHumanoid()
        local hp = hum and hum.Health or 0
        local maxHp = hum and hum.MaxHealth or 0
        local enemies = countKillableEnemies()
        local ore, oreNum = getHighestOre()

        local hoverStr = "—"
        if Farm.hoverTarget then
            hoverStr = ("(%.0f, %.0f, %.0f)"):format(
                Farm.hoverTarget.X, Farm.hoverTarget.Y, Farm.hoverTarget.Z)
        end

        infoPanel.Text = table.concat({
            ("  State: %s"):format(Farm.state),
            ("  Stage: %d / %d   (start %d)"):format(Farm.currentStage, MAX_STAGE, Farm.startStage),
            ("  Carried: %d / %d   Last method: %s"):format(
                Farm.oresCarried, Config.MaxCarry, Farm.lastLootMethod),
            ("  Enemies left: %d   Return clicks: %d"):format(enemies, Farm.spawnCalls),
            ("  Flight: %s   Target: %s"):format(
                Farm.state == "waiting" and "ON" or "off", hoverStr),
        }, "\n")

        statusBox.Text = table.concat({
            ("  Running: %s"):format(tostring(Farm.running)),
            ("  State: %s   Flight: %s"):format(
                Farm.state, Farm.state == "waiting" and "ON" or "off"),
            ("  Current stage: %d   Start stage: %d"):format(Farm.currentStage, Farm.startStage),
            ("  Health: %.0f / %.0f"):format(hp, maxHp),
            ("  Enemies killable: %d   zero streak: %d/%d"):format(
                enemies, Farm.zeroStreak, Config.EnemiesGoneChecks),
            ("  Highest ore in cache: %s"):format(ore and ore.Name or "(none)"),
            ("  Ores carried: %d / %d   Last method: %s"):format(
                Farm.oresCarried, Config.MaxCarry, Farm.lastLootMethod),
            ("  Stages passed: %d   Loops: %d   Deaths: %d"):format(
                Farm.stagesPassed, Farm.loopCount, Farm.deaths),
            ("  Flight height: %.0f   Responsiveness: %.1f"):format(
                Config.FlightHeight, Config.FlyGain),
            ("  Fly target: %s"):format(hoverStr),
            ("  Return click coord: (%d, %d)   count: %d"):format(
                BACK_X, BACK_Y, Farm.spawnCalls),
            ("  Current root: %s"):format(
                getRoot() and ("%.0f, %.0f, %.0f"):format(
                    getRoot().Position.X, getRoot().Position.Y, getRoot().Position.Z) or "?"),
        }, "\n")

        lastLogBox.Text = "  Last: " .. Farm.lastLog
        task.wait(0.35)
    end
end)

switchTab("farm")

log("Loaded.")
log(("Flight height: %.0f  Gain: %.1f  (adjust in Farm / Manual tabs).")
    :format(Config.FlightHeight, Config.FlyGain))
SerenityHub
SerenityHub script preview

SerenityHub

Developer
SerenityHub
Updated
Updated
NO KEY PC MOBILE

In our test, Auto Forge crafted no gear, and Auto World Boss didn’t teleport to the boss. We didn’t check the main Auto Farm, so the rest of the list is as the developer describes it.

  • God Mode
  • Instant Kill
  • Instant Ore Mining
  • +38 more
Limitation: Don’t rely on it for forging or the World Boss for now.
Copies 1 Discord
Details

Functions

  • God Mode
  • Instant Kill
  • Instant Ore Mining
  • Ore Filter
  • Auto Rebirth
  • Auto Train
  • Auto Upgrade
  • Auto Tower
  • Starting Tower Stage
  • Auto Equip Best Sword
  • Auto Equip Best Armor
  • Auto Equip Best Hat
  • Auto Index Rewards
  • Auto Online Rewards
  • Auto Forge
  • Forge Target Selection
  • Specific Ore Selection
  • Auto Forge Best Ore
  • Auto Sell Equipment
  • Weapon Rarity Sell Filter
  • Helmet Rarity Sell Filter
  • Armor Rarity Sell Filter
  • Specific Equipment Sell Filter
  • Auto Sell Ores
  • Ore Rarity Sell Filter
  • Ore Sell Order
  • Auto Enhance Equipment
  • Max Enhance Level
  • Use Protection Scroll
  • Auto Enchant Equipment
  • Rune Rarity Filter
  • Specific Rune Selection
  • Auto Enchant Best Equipment
  • Instant Dungeon
  • Auto Dungeon Stage Selection
  • Auto Season
  • Auto Claim Daily Ticket
  • Auto Claim Season Track Rewards
  • Auto Luck
  • Auto World Boss
  • Auto Claim Boss Reward
Access
NO KEY
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet(
    "https://raw.githubusercontent.com/MUshihara/Serenity-hub/main/loader.lua"
))()
Mysrix Hub
Mysrix Hub script preview

Mysrix Hub

Developer
czm
Updated
Updated
NO KEY PC MOBILE
  • Auto Farm
  • Instant Forge
  • Frost Tower Auto Farm
  • +12 more
Limitation: No results from our test yet. Features are as listed by the developer.
Copies 1 Discord
Details

Functions

  • Auto Farm
  • Instant Forge
  • Frost Tower Auto Farm
  • Stage Selection
  • Ore Selection
  • Auto Upgrade Ore Count
  • Auto Upgrade Luck Boost
  • Auto Upgrade Train Boost
  • Auto Claim Online Rewards
  • Auto Claim Index Rewards
  • Instant Kill
  • God Mode
  • Auto Rebirth
  • Auto Train
  • Tower Wave Selection
Access
NO KEY
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://raw.githubusercontent.com/ummarxfarooq/mystrix-hub/refs/heads/main/loader"))()

KEY SYSTEM Scripts

These three ask for a key before they run. A key system isn’t the same as a paid script, and the steps to get a key depend on the developer. From this group, we tested Apel Hub.

Apel Hub
Apel Hub script preview

Apel Hub

Developer
Apelsinka
Updated
Updated
Working
KEY SYSTEM PC MOBILE

In our test, farming worked overall, and the Automation Priority Order was respected. We set Yeti as the target race in Auto Roll Race, got it on the fifth roll, and the script stopped spending rolls right there.

  • Auto Farm
  • Auto Roll Race
  • Target Race Selection
  • +25 more
Limitation: Needs a key. No Forge in its feature list. Yeti on the fifth roll was one session, not the drop odds.
Copies 2 Discord
Details

Functions

  • Auto Farm
  • Auto Roll Race
  • Target Race Selection
  • God Mode
  • One Hit Kill
  • Auto Super Loot
  • Super Loot Rarity Filter
  • Auto Equip Best Gear
  • Auto Sell Weaker Gear
  • Auto Sell Gear by Rarity
  • Auto Sell Selected Ores
  • Auto Train
  • Auto Teleport to Best Training Area
  • Auto Rebirth
  • Auto Upgrade
  • Select Upgrades to Buy
  • Auto Enchant Gear
  • Select Enchant Stones
  • Auto Claim Rewards
  • Auto Server Hop
  • Server Hop Interval
  • Auto Use Potions
  • Keep Selected Potion Buffs Active
  • Performance Mode
  • Ultra Performance Mode
  • Discord Webhook Notifications
  • Webhook Rarity Filter
  • Automation Priority Order
Access
KEY SYSTEM
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://apelhub.com/loader.lua"))()
Vyral
Vyral script preview

Vyral

Developer
fxka
Updated
Updated
Not tested
KEY SYSTEM PC MOBILE
  • Dungeon Farming
  • Frozen Tower Auto Farm
  • Auto Forge
  • +19 more
Limitation: Needs a key; not tested. Lists World Boss fighting, the one task none of our tested hubs handled.
Copies 0 Discord
Details

Functions

  • Dungeon Farming
  • Frozen Tower Auto Farm
  • Auto Forge
  • Automatic stage choice based on your damage
  • Ignore Damage Limit for manual stage choice
  • Force Kill and Exit Fight buttons
  • Tower: starting round, round progression or repeating one round
  • Tower: Daily Tower Ticket claim, Force Kill and manual exit
  • Forge: weapons or armor, ore rarity filter and best-ore priority
  • Forge: ore per craft, ore reserve, live forge odds, auto equip of the best result and manual forging
  • Ore Collection with rarity filters and a searchable ore list
  • Auto Training with automatic area choice
  • Auto Click with adjustable speed
  • World Boss: auto join, attack with equipped weapon, claim the reward card
  • World Boss spawn countdown and boss status; normal farming pauses during the fight
  • Auto Sell by item type and rarity with reserves and sell interval; equipped and locked items are kept
  • Auto Rebirth and selected training, luck and ore-pack upgrades with a minimum coin reserve
  • Auto Claim: online, index, event quest, daily tower ticket, offline and update rewards
  • WalkSpeed, flight speed, Noclip, Infinite Jump
  • God Mode (local damage protection) and instant proximity prompts
  • Live status: training, ore, forged items, clicks, tower, boss, coins, power, level, rebirths
  • Anti-AFK, per-account configs, auto save, menu keybind, rejoin and unload
Access
KEY SYSTEM
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://jnkie.com/loaders/vyral"))()
BP Hub
BP Hub script preview

BP Hub

Developer
bypasshub
Updated
Updated
Not tested
KEY SYSTEM PC MOBILE
  • Stage Farm
  • Auto Forge
  • Tower Farm
  • +15 more
Limitation: Needs a key; not tested. Lists World Boss fighting, the one task none of our tested hubs handled.
Copies 0
Details

Functions

  • Stage Farm
  • Auto Forge
  • Tower Farm
  • Stage Farm clears stages in order, then farms your stage
  • Forge Leaderboard mode
  • Tower start round and number of rounds
  • God Mode
  • World Boss: dodges attacks, skips bosses that won’t die, picks the reward card
  • Ore Collect with rarity filter and Golden Goblin hunting
  • Auto Sell that keeps your best items
  • Equip Best, Auto Lock, auto hat and armor
  • Auto Enhance with Protection Scrolls, Auto Runes
  • Auto Click and training area selection
  • Upgrades, Rebirth, Potions, Race Roll
  • Auto Claim: online, offline, index, season pass, quests and codes
  • Webhook for rare forges, goblins and boss cards
  • Fly, Noclip, Speed, Infinite Jump, Teleports
  • FPS Boost, Black Screen, Anti-AFK, Rejoin, Server Hop
Access
KEY SYSTEM
Tags
PC MOBILE
Languages
English
Compatibility
Delta Arceus X Codex Other
Script code
loadstring(game:HttpGet("https://api.luarmor.net/files/v4/loaders/467778b7e06d29cb032367938bfa7210.lua"))()

Before You Leave a Script Running

Paste the code into your executor while you’re in +1 Loot To Forge by Good Bro Studio. Key-system hubs ask for a key first.

  1. If the hub has a separate ore-collection switch, like Auto Collect Ore in Ouroboros, turn it on too.
  2. Pick a stage your weapon can clear and the ore rarities you want.
  3. Watch one full run: you should come back with ore, and the next run should start.
  4. After a rejoin, run the script again. A rebirth doesn’t stop it: it keeps farming the dungeons you can reach.
Running scripts breaks Roblox’s Terms of Use and can get an account banned. Use an account you can afford to lose.