-- [[ Rscripts Risk Notice ]] -- This script is not verified by rscripts.net. Deal with caution. -- -- Stay safe: -- • Never log in on unofficial Roblox sites or lookalike domains. -- • Real Roblox links use roblox.com (check the .com ending). -- • Treat fake Roblox login / "claim reward" pages as phishing. -- [[ End Rscripts Risk Notice ]] --[[ Miners World - Auto Buy (Pickaxes, Backpacks, Luck, Speed, Jump, Jackhammer, Explosions + Mining Speed) Buys the next pickaxe, backpack, luck, speed, and jump levels as soon as you can afford them. Uses the game's own cost formulas and the same call the shop buttons make. Also includes unlocked lobby teleports and native upgrade-screen shortcuts. Includes recipe tracking and native auto-crafting when materials are ready. Includes an opt-in mode that adds Emeralds to native AutoMine targeting. The Speed Hub X UI sources are pinned to the inspected GitHub revisions. RightShift = hide / show × = unload (or getgenv().__MWG_UNLOAD()) Settings are remembered in minersworld_autobuy_test.json ]] local PLACE_ID = 9404223526 print("[MWG] Test script started in place", game.PlaceId) if game.PlaceId ~= PLACE_ID then warn("[MWG] This script only runs in Miners World (place " .. PLACE_ID .. ")") return end if not game:IsLoaded() then game.Loaded:Wait() end local env = (getgenv and getgenv()) or _G if env.__MWG_UNLOAD then pcall(env.__MWG_UNLOAD) end if env.__MW_UNLOAD then pcall(env.__MW_UNLOAD) end -- older all-in-one version local RS = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local UIS = game:GetService("UserInputService") local Http = game:GetService("HttpService") local TweenService = game:GetService("TweenService") local RunService = game:GetService("RunService") local Stats = game:GetService("Stats") local Workspace = game:GetService("Workspace") local lp = Players.LocalPlayer local uiLibrary local libraryGuis = {} local libraryWindowGui ---------------------------------------------------------------------- -- Game modules + data ---------------------------------------------------------------------- local Modules = RS:WaitForChild("Modules") local DataModule = require(Modules:WaitForChild("DataModule")) local Networking = require(Modules:WaitForChild("Networking")) local GD = require(Modules:WaitForChild("GameDefinition")) local FH = require(Modules:WaitForChild("FormulaHandler")) local GuiHandler = require(Modules:WaitForChild("GuiHandler")) local Translator = require(Modules:WaitForChild("Translator")) local data for _ = 1, 120 do local ok, d = pcall(DataModule.GetData, lp) if ok and d and d:FindFirstChild("Others") and d.Others:FindFirstChild("Loaded") and d.Others.Loaded.Value then data = d break end task.wait(0.5) end if not data then warn("[MWG] player data never finished loading") return end local gameFrames = lp:WaitForChild("PlayerGui"):WaitForChild("Game"):WaitForChild("Frames") ---------------------------------------------------------------------- -- Settings ---------------------------------------------------------------------- local FILE = "minersworld_autobuy_test.json" local S = { master = true, Pickaxe = true, Backpack = true, Luck = true, Speed = true, Jump = true, Jackhammer = true, Explosions = true, MiningSpeed = true, AutoCraft = false, AutoPinNextCraft = true, HideExplosiveEffects = true, WalkSpeed = 16, IncludeEmeraldsInAutoMine = false, } pcall(function() if isfile and isfile(FILE) then local saved = Http:JSONDecode(readfile(FILE)) for k in pairs(S) do if type(saved[k]) == type(S[k]) then S[k] = saved[k] end end if type(saved.IncludeEmeraldsInAutoMine) ~= "boolean" and type(saved.EmeraldOnlyAutoMine) == "boolean" then S.IncludeEmeraldsInAutoMine = saved.EmeraldOnlyAutoMine end end end) S.WalkSpeed = math.clamp(S.WalkSpeed, 16, 90) local function save() pcall(function() if writefile then writefile(FILE, Http:JSONEncode(S)) end end) end local EMERALD_BLOCK_ID = 863 local emeraldTargetingActive = false local emeraldTargetingOriginals local function restoreEmeraldTargeting() emeraldTargetingActive = false local originals = emeraldTargetingOriginals if not originals then return end local ok, err = pcall(function() GD.RarityMap[EMERALD_BLOCK_ID] = originals.rarity GD.Unobtainable[EMERALD_BLOCK_ID] = originals.unobtainable end) if ok then emeraldTargetingOriginals = nil else warn("[MWG] could not restore Emerald AutoMine eligibility:", err) end end local function enableEmeraldTargeting() if type(GD.RarityMap) ~= "table" or type(GD.Unobtainable) ~= "table" then error("[MWG] Emerald AutoMine unavailable: game eligibility maps are missing", 0) end local originalRarity = GD.RarityMap[EMERALD_BLOCK_ID] local originalUnobtainable = GD.Unobtainable[EMERALD_BLOCK_ID] emeraldTargetingOriginals = { rarity = originalRarity, unobtainable = originalUnobtainable, } local eligibilityOk, eligibilityError = pcall(function() -- Preserve every native candidate; only add Emerald to the eligible rarity pool. GD.RarityMap[EMERALD_BLOCK_ID] = 5 GD.Unobtainable[EMERALD_BLOCK_ID] = nil end) if not eligibilityOk then restoreEmeraldTargeting() error( "[MWG] could not enable Emerald AutoMine eligibility: " .. tostring(eligibilityError), 0 ) end emeraldTargetingActive = true end local function setIncludeEmeraldsInAutoMine(enabled) if enabled then if not emeraldTargetingActive then enableEmeraldTargeting() end S.IncludeEmeraldsInAutoMine = true print("[MWG] Emerald added to native AutoMine targets") else S.IncludeEmeraldsInAutoMine = false restoreEmeraldTargeting() print("[MWG] Emerald removed from native AutoMine targets") end save() end ---------------------------------------------------------------------- -- Buying logic ---------------------------------------------------------------------- local ITEMS = { { cat = "Pickaxe", title = "Pickaxe" }, { cat = "Backpack", title = "Backpack" }, { cat = "Luck", title = "Luck" }, { cat = "Speed", title = "Speed" }, { cat = "Jump", title = "Jump" }, } local UPGRADE_GROUPS = { { setting = "Jackhammer", title = "Jackhammer", ids = { "2_1", "2_2", "2_3" } }, { setting = "Explosions", title = "Explosions", ids = { "4_1", "4_2", "4_3" } }, { setting = "MiningSpeed", title = "Mining Speed", ids = { "3_1", "3_2" } }, } local UPGRADE_ITEMS = {} for _, group in ipairs(UPGRADE_GROUPS) do for _, upgradeId in ipairs(group.ids) do UPGRADE_ITEMS[#UPGRADE_ITEMS + 1] = { setting = group.setting, title = group.title, id = upgradeId, } end end local bought = { Pickaxe = 0, Backpack = 0, Luck = 0, Speed = 0, Jump = 0 } local lastAction = nil local lastNetworkAction = -math.huge local BASE_ACTION_DELAY = 0.4 local MAX_ACTION_DELAY = 2.5 local function canSendAutomaticAction() local delay = BASE_ACTION_DELAY local ok, ping = pcall(function() return Stats.Network.ServerStatsItem["Data Ping"]:GetValue() end) if ok and type(ping) == "number" then delay = math.clamp(ping / 1000 * 2.5, BASE_ACTION_DELAY, MAX_ACTION_DELAY) end return os.clock() - lastNetworkAction >= delay end local function noteNetworkAction() lastNetworkAction = os.clock() end local function removeExplosiveEffect(instance) if S.HideExplosiveEffects and instance:IsA("Explosion") then instance:Destroy() end end local function setExplosiveEffectsHidden(hidden) S.HideExplosiveEffects = hidden if hidden then for _, instance in ipairs(Workspace:GetDescendants()) do removeExplosiveEffect(instance) end end save() end local function parts(cat) local def = GD.Formulas.Equipables[cat] local ul = data.Equipables.Unlocked:FindFirstChild(cat) local wallet = def and data.NumberValues:FindFirstChild(def.Currency) return def, ul, wallet end -- how many levels (1-5) we can afford right now; the shop lets you buy up to 5 ahead local function decide(cat, have) local def, ul = parts(cat) if not (def and ul) or def.FirstBuyable then return nil end local lvl = ul.Value for n = 5, 1, -1 do local idx = lvl + n if not def.MaxLevel or idx <= def.MaxLevel then local ok, cost = pcall(FH.GetEquipableCostForMultiple, data, cat, n) if ok and type(cost) == "number" and cost <= have then return n, idx, cost, lvl end end end end env.__MWG_DECIDE = decide -- debug helper -- if a purchase doesn't change the level, back off (the server said no) local attempts = {} local function blocked(key, level) local a = attempts[key] if not a or a.level ~= level then return false end return os.clock() - a.t < math.min(5 * 2 ^ a.fails, 30) end local function noteAttempt(key, level) local a = attempts[key] if a and a.level == level then a.fails += 1 a.t = os.clock() else attempts[key] = { level = level, fails = 0, t = os.clock() } end end local function stepItem(item) if not S[item.cat] then return false end local _, _, wallet = parts(item.cat) if not wallet then return false end local n, idx, _, lvl = decide(item.cat, wallet.Value) if not n or blocked(item.cat, lvl) or not canSendAutomaticAction() then return false end noteAttempt(item.cat, lvl) noteNetworkAction() Networking.Fire("Equip", item.cat, idx) bought[item.cat] += n lastAction = string.format("Bought %s %d → %d", item.title, lvl, idx) return true end local function stepUpgrade(item) if not S[item.setting] then return false end local definition = GD.Formulas.Upgrades[item.id] if not definition or type(definition.Cost) ~= "function" then warn("[MWG] missing upgrade formula for", item.id) return false end local okLevel, levelValue = pcall(FH.GetUpgrade, data, item.id) if not okLevel then warn("[MWG] could not read upgrade level " .. item.id .. ":", levelValue) return false end local level = levelValue and levelValue.Value if type(level) ~= "number" or type(definition.MaxLevel) ~= "number" or level >= definition.MaxLevel then return false end local currencyName = type(definition.Currency) == "string" and string.match(definition.Currency, "^NumberValues%.(.+)$") local wallet = currencyName and data.NumberValues:FindFirstChild(currencyName) if not wallet then warn("[MWG] missing upgrade currency for", item.id, definition.Currency) return false end local okCost, cost = pcall(definition.Cost, level) if not okCost then warn("[MWG] could not calculate upgrade cost " .. item.id .. ":", cost) return false end local attemptKey = "Upgrade:" .. item.id if type(cost) ~= "number" or cost > wallet.Value or blocked(attemptKey, level) or not canSendAutomaticAction() then return false end local ok, err = pcall(Networking.Fire, "BuyUpgrade", item.id) if not ok then warn("[MWG] native upgrade request failed for " .. item.id .. ":", err) return false end noteAttempt(attemptKey, level) noteNetworkAction() lastAction = string.format("Bought %s upgrade %d → %d", item.title, level, level + 1) return true end local function step(tick) -- Rotate all purchase types through the shared action throttle. local totalItems = #ITEMS + #UPGRADE_ITEMS local first = tick % totalItems + 1 for i = 0, totalItems - 1 do local index = ((first - 1 + i) % totalItems) + 1 if index <= #ITEMS then if stepItem(ITEMS[index]) then return end elseif stepUpgrade(UPGRADE_ITEMS[index - #ITEMS]) then return end end end ---------------------------------------------------------------------- -- Number formatting ---------------------------------------------------------------------- local SUFFIX = { "", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "Dc" } local function abbr(n) if type(n) ~= "number" or n ~= n then return "?" end if n == math.huge then return "∞" end if n < 1000 then if n == math.floor(n) then return tostring(n) end return string.format("%.1f", n) end local e = math.min(math.floor(math.log10(n) / 3), #SUFFIX - 1) local v = n / 10 ^ (e * 3) local s = string.format((v >= 100 and "%.0f") or (v >= 10 and "%.1f") or "%.2f", v) if s:find(".", 1, true) then s = s:gsub("0+$", "") s = s:gsub("%.$", "") end return s .. SUFFIX[e + 1] end ---------------------------------------------------------------------- -- UI helpers ---------------------------------------------------------------------- local C = { bgTop = Color3.fromRGB(28, 31, 43), bgBot = Color3.fromRGB(17, 19, 26), card = Color3.fromRGB(30, 34, 46), track = Color3.fromRGB(15, 17, 23), text = Color3.fromRGB(236, 239, 247), muted = Color3.fromRGB(131, 139, 162), accent = Color3.fromRGB(242, 65, 65), ok = Color3.fromRGB(96, 214, 148), off = Color3.fromRGB(58, 63, 82), danger = Color3.fromRGB(235, 96, 112), } local animateButton local function new(class, props, parent) local o = Instance.new(class) for k, v in pairs(props) do o[k] = v end if class == "TextLabel" or class == "TextButton" or class == "TextBox" then local fontName = o.Font.Name if string.find(fontName, "ExtraBold") or string.find(fontName, "Black") then o.Font = Enum.Font.BuilderSansExtraBold elseif string.find(fontName, "Bold") then o.Font = Enum.Font.BuilderSansBold elseif string.find(fontName, "Medium") or string.find(fontName, "Semibold") then o.Font = Enum.Font.BuilderSansMedium else o.Font = Enum.Font.BuilderSans end if type(props.TextSize) == "number" then o.TextSize = props.TextSize + 1 end end if parent then o.Parent = parent end if animateButton and o:IsA("GuiButton") then animateButton(o) end return o end local function corner(o, r) return new("UICorner", { CornerRadius = UDim.new(0, r) }, o) end local function outline(o, transparency) return new("UIStroke", { Color = Color3.new(1, 1, 1), Transparency = transparency or 0.92, Thickness = 1, ApplyStrokeMode = Enum.ApplyStrokeMode.Border, }, o) end local function label(parent, props) local p = { BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextColor3 = C.text, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Center, Text = "", } for k, v in pairs(props) do p[k] = v end return new("TextLabel", p, parent) end local function tween(o, t, props) local animation = TweenService:Create(o, TweenInfo.new(t, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), props) animation:Play() return animation end local conns = {} local function track(c) conns[#conns + 1] = c return c end track(Workspace.DescendantAdded:Connect(removeExplosiveEffect)) local switchRenders = {} animateButton = function(button) local scale = new("UIScale", { Scale = 1 }, button) button.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then tween(scale, 0.08, { Scale = 0.94 }) end end) button.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then tween(scale, 0.12, { Scale = 1 }) end end) end local function makeSwitch(parent, pos, get, set) local sw = new("TextButton", { Size = UDim2.fromOffset(40, 22), Position = pos, Text = "", AutoButtonColor = false, BackgroundColor3 = C.off, BorderSizePixel = 0, }, parent) corner(sw, 11) local knob = new("Frame", { Size = UDim2.fromOffset(16, 16), Position = UDim2.fromOffset(3, 3), BackgroundColor3 = Color3.new(1, 1, 1), BorderSizePixel = 0, }, sw) corner(knob, 8) local function render(animate) local on = get() local t = animate and 0.16 or 0 tween(sw, t, { BackgroundColor3 = on and C.accent or C.off }) tween(knob, t, { Position = UDim2.fromOffset(on and 21 or 3, 3) }) end sw.MouseButton1Click:Connect(function() set(not get()) render(true) save() end) render(false) switchRenders[#switchRenders + 1] = function() render(false) end return sw end ---------------------------------------------------------------------- -- UI ---------------------------------------------------------------------- local uiRoot do local ok, r = pcall(function() return (gethui and gethui()) or game:GetService("CoreGui") end) uiRoot = (ok and r) or lp:WaitForChild("PlayerGui") end local gui = new("ScreenGui", { Name = "MWG" .. math.random(1000, 9999), ResetOnSpawn = false, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, DisplayOrder = 1000, }) pcall(function() if syn and syn.protect_gui then syn.protect_gui(gui) end end) gui.Parent = uiRoot gui.Enabled = false local win local function colorSequence() local tinted = C.bgBot:Lerp(C.accent, 0.12) return ColorSequence.new({ ColorSequenceKeypoint.new(0, C.bgTop), ColorSequenceKeypoint.new(0.52, tinted), ColorSequenceKeypoint.new(1, C.bgBot), }) end local function addSurfaceGradient(surface) return new("UIGradient", { Rotation = 25, Color = ColorSequence.new(C.card, C.card:Lerp(C.accent, 0.08)), }, surface) end win = new("Frame", { Name = "Window", AnchorPoint = Vector2.new(0, 0.5), Position = UDim2.new(0, 40, 0.5, 0), Size = UDim2.fromOffset(420, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundColor3 = Color3.new(1, 1, 1), BorderSizePixel = 0, Active = true, }, gui) corner(win, 14) outline(win, 0.86) new("UIGradient", { Rotation = 90, Color = colorSequence() }, win) new("UIPadding", { PaddingTop = UDim.new(0, 14), PaddingBottom = UDim.new(0, 14), PaddingLeft = UDim.new(0, 14), PaddingRight = UDim.new(0, 14), }, win) new("UIListLayout", { Padding = UDim.new(0, 12), SortOrder = Enum.SortOrder.LayoutOrder }, win) -- header ------------------------------------------------------------ local header = new("Frame", { Size = UDim2.new(1, 0, 0, 40), BackgroundTransparency = 1, LayoutOrder = 1 }, win) local headerAccent = new("Frame", { Size = UDim2.new(0, 250, 0, 2), Position = UDim2.fromOffset(0, 38), BackgroundColor3 = C.accent, BorderSizePixel = 0, }, header) new("UIGradient", { Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0.08), NumberSequenceKeypoint.new(1, 1), }), }, headerAccent) local dragArea = new("Frame", { Size = UDim2.fromOffset(160, 40), BackgroundTransparency = 1, Active = true, }, header) label(dragArea, { Text = "MINERS WORLD", Font = Enum.Font.GothamBold, TextSize = 10, TextColor3 = C.accent, Size = UDim2.new(1, 0, 0, 12), Position = UDim2.fromOffset(0, 3), }) label(dragArea, { Text = "Auto Buy", Font = Enum.Font.GothamBold, TextSize = 17, Size = UDim2.new(1, 0, 0, 24), Position = UDim2.fromOffset(0, 15), }) local function headerButton(text, x, color) local b = new("TextButton", { Size = UDim2.fromOffset(22, 22), Position = UDim2.fromOffset(x, 9), BackgroundColor3 = C.card, Text = text, TextColor3 = color or C.muted, Font = Enum.Font.GothamBold, TextSize = 15, AutoButtonColor = false, BorderSizePixel = 0, }, header) corner(b, 6) b.MouseEnter:Connect(function() tween(b, 0.12, { BackgroundColor3 = C.off }) end) b.MouseLeave:Connect(function() tween(b, 0.12, { BackgroundColor3 = C.card }) end) return b end local closeBtn = headerButton("×", 366) local collapseBtn = headerButton("–", 338) makeSwitch(header, UDim2.fromOffset(286, 9), function() return S.master end, function(v) S.master = v end) -- body -------------------------------------------------------------- local PAGE_HEIGHT = 524 local body = new("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 2, }, win) local sidebar = new("Frame", { Size = UDim2.new(0, 76, 0, 226), BackgroundTransparency = 1, }, body) local mainPage = new("ScrollingFrame", { Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0), BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5, CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y, }, body) new("UIListLayout", { Padding = UDim.new(0, 10), SortOrder = Enum.SortOrder.LayoutOrder }, mainPage) local teleportPage = new("Frame", { Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0), BackgroundTransparency = 1, Visible = false, }, body) label(teleportPage, { Text = "Lobbies", Font = Enum.Font.GothamBold, TextSize = 15, Size = UDim2.new(1, 0, 0, 20), Position = UDim2.fromOffset(0, 0), }) label(teleportPage, { Text = "Only lobbies unlocked by the game are available.", TextSize = 11, TextColor3 = C.muted, TextWrapped = true, Size = UDim2.new(1, 0, 0, 32), Position = UDim2.fromOffset(0, 24), }) local lobbyList = new("ScrollingFrame", { Size = UDim2.new(1, 0, 0, PAGE_HEIGHT - 68), Position = UDim2.fromOffset(0, 62), BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5, CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y, }, teleportPage) new("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder }, lobbyList) local function makeTab(text, order) local button = new("TextButton", { Size = UDim2.new(1, 0, 0, 36), Position = UDim2.fromOffset(0, (order - 1) * 44), BackgroundColor3 = C.off, Text = text, TextColor3 = C.text, Font = Enum.Font.GothamBold, TextSize = 10, AutoButtonColor = false, BorderSizePixel = 0, }, sidebar) corner(button, 8) return button end local mainTab = makeTab("Main", 1) local teleportsTab = makeTab("Teleports", 2) local upgradesTab = makeTab("Upgrades", 3) local profileImage = new("ImageLabel", { Name = "ProfileAvatar", AnchorPoint = Vector2.new(0.5, 0), Size = UDim2.fromOffset(30, 30), Position = UDim2.new(0.5, 0, 0, 174), BackgroundColor3 = C.card, BorderSizePixel = 0, Image = "", ScaleType = Enum.ScaleType.Crop, }, sidebar) corner(profileImage, 15) outline(profileImage, 0.35) label(sidebar, { Name = "ProfileUsername", Text = lp.Name, TextSize = 10, TextXAlignment = Enum.TextXAlignment.Center, TextTruncate = Enum.TextTruncate.AtEnd, Size = UDim2.new(1, -4, 0, 16), Position = UDim2.fromOffset(2, 206), }) task.spawn(function() local ok, image = pcall(function() return Players:GetUserThumbnailAsync(lp.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48) end) if not ok then warn("[MWG] could not load player profile image:", image) return end if profileImage.Parent then profileImage.Image = image end end) local upgradeScreens = { { frame = "Upgrades", title = "Upgrades" }, { frame = "Gauntlets", title = "Gauntlets" }, { frame = "Crafting", title = "Crafting" }, { frame = "Explosion", title = "Explosions" }, { frame = "Jackhammer", title = "Jackhammer" }, { frame = "MiningSpeed", title = "Mining Speed" }, { frame = "Prestige", title = "Prestige" }, { frame = "Range", title = "Range" }, { frame = "Sacrifice", title = "Sacrifice" }, } local function loadPinnedModule(url, label) local source = game:HttpGet(url) local chunk, compileError = loadstring(source, "@MWG/" .. label) if not chunk then error("[MWG] failed to compile " .. label .. ": " .. tostring(compileError)) end return chunk() end local rootOk, libraryRoot = pcall(function() return (gethui and gethui()) or game:GetService("CoreGui") end) if not rootOk or not libraryRoot then error("[MWG] could not access the UI root for Speed Hub X") end local previousGuiInstances = {} for _, child in ipairs(libraryRoot:GetChildren()) do previousGuiInstances[child] = true end loadPinnedModule( "https://raw.githubusercontent.com/AhmadV99/Speed-Hub-X/main/Settings.lua", "Settings.lua" ) local FuncsV3 = loadPinnedModule( "https://raw.githubusercontent.com/AhmadV99/Main/main/Library/Example/FuncsV3", "FuncsV3" ) -- The selected library revision enables its own anti-AFK behavior on initialization. local SpeedHubLibrary = loadPinnedModule( "https://raw.githubusercontent.com/mamafoni281/Speed-hub-x-V5.0-Library/refs/heads/main/Speed-Hub-X-5.0-Library-Source", "Speed-Hub-X-5.0-Library" ) FuncsV3:SetTable(S) uiLibrary = SpeedHubLibrary:CreateWindow({ ["Tab Width"] = 160, ["Description"] = "", ["Title"] = "Speed Hub X | Miners World", ["SizeUi"] = UDim2.fromOffset(650, 520), }) for _, child in ipairs(libraryRoot:GetChildren()) do if not previousGuiInstances[child] and child:IsA("ScreenGui") then libraryGuis[#libraryGuis + 1] = child if child:FindFirstChild("DropShadowHolder") then libraryWindowGui = child end end end if not libraryWindowGui then warn("[MWG] could not find the Speed Hub window for the Emerald counter") else local emeraldCounterHolder = libraryWindowGui:FindFirstChild("DropShadowHolder") local minimizeButton for _, descendant in ipairs(libraryWindowGui:GetDescendants()) do if descendant:IsA("TextButton") and descendant.Name == "Min" then minimizeButton = descendant break end end local counterScreenGui = new("ScreenGui", { Name = "MWGEmeraldCounter", ResetOnSpawn = false, DisplayOrder = libraryWindowGui.DisplayOrder + 1, }, libraryRoot) libraryGuis[#libraryGuis + 1] = counterScreenGui local emeraldCounter = new("Frame", { Name = "EmeraldCounter", AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, -16, 0, 16), Size = UDim2.fromOffset(190, 42), BackgroundColor3 = C.card, BackgroundTransparency = 0.08, BorderSizePixel = 0, Visible = false, ZIndex = 100, }, counterScreenGui) corner(emeraldCounter, 9) outline(emeraldCounter, 0.82) local emeraldCountLabel = label(emeraldCounter, { Name = "EmeraldCount", Text = "Emeralds broken today: --", Font = Enum.Font.GothamBold, TextSize = 12, TextColor3 = C.text, TextXAlignment = Enum.TextXAlignment.Center, Size = UDim2.new(1, -16, 1, 0), Position = UDim2.fromOffset(8, 0), ZIndex = 101, }) local dailyEmeralds = data.Others:FindFirstChild("EmeraldsMinedDaily") if dailyEmeralds and dailyEmeralds:IsA("ValueBase") then local function updateEmeraldCount() emeraldCountLabel.Text = "Emeralds broken today: " .. tostring(dailyEmeralds.Value) end updateEmeraldCount() track(dailyEmeralds:GetPropertyChangedSignal("Value"):Connect(updateEmeraldCount)) else warn("[MWG] Emerald counter unavailable: daily mined count was not found") end local function updateEmeraldCounterVisibility() emeraldCounter.Visible = libraryWindowGui.Enabled and emeraldCounterHolder ~= nil and not emeraldCounterHolder.Visible end if emeraldCounterHolder then track(emeraldCounterHolder:GetPropertyChangedSignal("Visible"):Connect(updateEmeraldCounterVisibility)) end track(libraryWindowGui:GetPropertyChangedSignal("Enabled"):Connect(updateEmeraldCounterVisibility)) if minimizeButton then track(minimizeButton.Activated:Connect(function() task.defer(updateEmeraldCounterVisibility) end)) end updateEmeraldCounterVisibility() end local homeTab = uiLibrary:CreateTab({ Name = "Home", Icon = "rbxassetid://10723407389" }) local mainBuySection = homeTab:AddSection("Auto Buy (Pickaxe, Backpack)", false) local function bindToggle(section, title, description, key) FuncsV3:Toggle(section, title, description, S[key], function(value) S[key] = value save() end) end bindToggle(mainBuySection, "Auto Buy", "Master switch for automation", "master") bindToggle(mainBuySection, "Pickaxe", "Automatically buy pickaxe upgrades", "Pickaxe") bindToggle(mainBuySection, "Backpack", "Automatically buy backpack upgrades", "Backpack") local movementBuySection = homeTab:AddSection("Auto Buy (Luck, Jump, Speed)", false) bindToggle(movementBuySection, "Luck", "Automatically buy Luck upgrades", "Luck") bindToggle(movementBuySection, "Jump", "Automatically buy Jump upgrades", "Jump") bindToggle(movementBuySection, "Speed", "Automatically buy Speed upgrades", "Speed") local autoMineTargetSection = homeTab:AddSection("AutoMine Targeting", false) local function updateIncludeEmeraldsInAutoMine(enabled) local ok, err = pcall(setIncludeEmeraldsInAutoMine, enabled) if not ok then S.IncludeEmeraldsInAutoMine = false restoreEmeraldTargeting() save() warn("[MWG] adding Emeralds to AutoMine failed:", err) end end if S.IncludeEmeraldsInAutoMine then updateIncludeEmeraldsInAutoMine(true) end FuncsV3:Toggle( autoMineTargetSection, "Include Emeralds in AutoMine", "Adds Emeralds to native AutoMine candidates; other normal targets remain enabled", S.IncludeEmeraldsInAutoMine, updateIncludeEmeraldsInAutoMine ) local playerMovementSection = homeTab:AddSection("Player Movement", false) local function applyWalkSpeed(character) local humanoid = character and character:FindFirstChildOfClass("Humanoid") if humanoid then humanoid.WalkSpeed = S.WalkSpeed end end track(lp.CharacterAdded:Connect(function(character) task.spawn(function() local humanoid = character:WaitForChild("Humanoid", 10) if humanoid then humanoid.WalkSpeed = S.WalkSpeed elseif character.Parent then warn("[MWG] could not apply walk speed: character has no Humanoid") end end) end)) playerMovementSection:AddSlider({ Title = "Player Walk Speed", Content = "Normal speed is 16; adjust up to 90", Increment = 1, Min = 16, Max = 90, Default = S.WalkSpeed, Callback = function(value) S.WalkSpeed = math.clamp(value, 16, 90) applyWalkSpeed(lp.Character) save() end, }) local advancedBuySection = homeTab:AddSection("Auto Buy (Jackhammer, Explosions, Mining Speed)", false) bindToggle(advancedBuySection, "Jackhammer", "Automatically buy Jackhammer upgrades", "Jackhammer") bindToggle(advancedBuySection, "Explosions", "Automatically buy Explosive upgrades", "Explosions") bindToggle(advancedBuySection, "Mining Speed", "Automatically buy Mining Speed upgrades", "MiningSpeed") local craftSection = homeTab:AddSection("Auto Crafter", false) local craftableAccessoryIds = {} for accessoryId, accessory in pairs(GD.Accessories) do for _, level in pairs(accessory.Levels or {}) do if type(level.Recipe) == "table" and #level.Recipe > 0 then craftableAccessoryIds[#craftableAccessoryIds + 1] = accessoryId break end end end table.sort(craftableAccessoryIds, function(a, b) local aNumber, bNumber = tonumber(a), tonumber(b) if aNumber and bNumber then return aNumber < bNumber end return tostring(a) < tostring(b) end) local observedCraftLevels = {} local pendingCraftCompletions = {} local function resetCraftCompletionTracking() table.clear(pendingCraftCompletions) for _, accessoryId in ipairs(craftableAccessoryIds) do local level = data.Accessories.Levels[accessoryId] observedCraftLevels[accessoryId] = level and level.Value or nil end end resetCraftCompletionTracking() for _, accessoryId in ipairs(craftableAccessoryIds) do local level = data.Accessories.Levels[accessoryId] if level then track(level:GetPropertyChangedSignal("Value"):Connect(function() local previousLevel = observedCraftLevels[accessoryId] local currentLevel = level.Value if S.AutoPinNextCraft and type(previousLevel) == "number" and type(currentLevel) == "number" and currentLevel > previousLevel then for completedLevel = previousLevel + 1, currentLevel do pendingCraftCompletions[#pendingCraftCompletions + 1] = { accessoryId = accessoryId, level = completedLevel, } end end observedCraftLevels[accessoryId] = currentLevel end)) end end local craftReadout = craftSection:AddParagraph({ Title = "Recipe Status", Content = "Auto Craft checks every accessory recipe. Auto Pin selects another recipe after a craft completes.", }) bindToggle(craftSection, "Auto Craft", "Automatically craft any accessory whose recipe materials are ready", "AutoCraft") FuncsV3:Toggle( craftSection, "Pin Next Recipe", "After a craft, pin another ready recipe or the next unpinned recipe; replaces the oldest pin if full", S.AutoPinNextCraft, function(value) S.AutoPinNextCraft = value resetCraftCompletionTracking() save() end ) local function getCraftPlan(accessoryId) local accessoryLevel = data.Accessories.Levels[accessoryId] if not accessoryLevel then return nil end local recipe = FH.GetRecipe(data, accessoryId) if type(recipe) ~= "table" or #recipe == 0 then return nil end local ready = true for _, ingredient in ipairs(recipe) do local blockId, required = ingredient[1], ingredient[2] local currentBlock = data.Blocks[blockId] local archivedBlock = data.ArchivedBlocks[blockId] local owned = (currentBlock and currentBlock.Value or 0) + (archivedBlock and archivedBlock.Value or 0) if owned < required then ready = false break end end if not ready then return nil end return { accessoryId = accessoryId, name = tostring(Translator.Get("Accessories." .. tostring(accessoryId) .. ".1.Name")), level = accessoryLevel.Value, } end local craftAttempts = {} local readyCraftPlans = {} local nextCraftPlanIndex = 1 local craftScanIndex = 1 local craftScanReadyPlans = {} local cachedCraftStatus local CRAFT_SCAN_BATCH_SIZE = 20 local function refreshCraftReadout() if not S.AutoCraft and not S.AutoPinNextCraft and not (libraryWindowGui and libraryWindowGui.Enabled) then return end local scanEnd = math.min(craftScanIndex + CRAFT_SCAN_BATCH_SIZE - 1, #craftableAccessoryIds) for index = craftScanIndex, scanEnd do local accessoryId = craftableAccessoryIds[index] local plan = getCraftPlan(accessoryId) if plan then craftScanReadyPlans[#craftScanReadyPlans + 1] = plan end end craftScanIndex = scanEnd + 1 if craftScanIndex <= #craftableAccessoryIds then return end readyCraftPlans = craftScanReadyPlans craftScanReadyPlans = {} craftScanIndex = 1 local status if #readyCraftPlans == 0 then status = "No accessory recipes are ready. Auto Craft will craft any recipe once its materials are available." else local readyRecipes = {} for _, plan in ipairs(readyCraftPlans) do readyRecipes[#readyRecipes + 1] = string.format("%s (level %d)", plan.name, plan.level + 1) end status = (#readyRecipes == 1 and "Ready: " or "Ready recipes: ") .. table.concat(readyRecipes, "\n") .. (S.AutoCraft and "\nAuto Craft is enabled." or "\nEnable Auto Craft to craft these.") end if status ~= cachedCraftStatus then cachedCraftStatus = status craftReadout:Set({ Title = "Recipe Status", Content = status }) end end local function pinnedRecipes() local pinned = {} local order = {} local raw = data.Others.PinnedRecipes.Value local count = 0 for value in string.gmatch(raw, "[^,]+") do local id = tonumber(value) if id then local key = tostring(id) if not pinned[key] then pinned[key] = true order[#order + 1] = id count += 1 end end end return pinned, count, order end local function nextRecipeToPin(completedAccessoryId, readyPlans, pinned) local ready = {} for _, plan in ipairs(readyPlans) do ready[tostring(plan.accessoryId)] = true end local completedIndex = 0 for index, accessoryId in ipairs(craftableAccessoryIds) do if tostring(accessoryId) == tostring(completedAccessoryId) then completedIndex = index break end end for pass = 1, 2 do for offset = 1, #craftableAccessoryIds do local index = ((completedIndex + offset - 1) % #craftableAccessoryIds) + 1 local accessoryId = craftableAccessoryIds[index] local key = tostring(accessoryId) local accessoryLevel = data.Accessories.Levels[accessoryId] local recipeCanBePinned = accessoryLevel ~= nil local hasNextRecipe = false if pass == 2 then local recipe = FH.GetRecipe(data, accessoryId) hasNextRecipe = type(recipe) == "table" and #recipe > 0 end if recipeCanBePinned and key ~= tostring(completedAccessoryId) and not pinned[key] and (pass == 1 and ready[key] or pass == 2 and hasNextRecipe) then return accessoryId end end end end local function stepPinNextRecipe() if not S.AutoPinNextCraft or #pendingCraftCompletions == 0 then return false end local completion = pendingCraftCompletions[1] local pinned, pinnedCount, pinnedOrder = pinnedRecipes() if completion.targetId and pinned[tostring(completion.targetId)] then table.remove(pendingCraftCompletions, 1) return false end if not completion.targetId then completion.targetId = nextRecipeToPin(completion.accessoryId, readyCraftPlans, pinned) if not completion.targetId then table.remove(pendingCraftCompletions, 1) return false end end if completion.awaitingPin then if os.clock() - completion.requestedAt < 5 then return false end completion.awaitingPin = false end if pinnedCount >= 5 then local completedKey = tostring(completion.accessoryId) local unpinId = pinned[completedKey] and completion.accessoryId or pinnedOrder[1] if not unpinId then return false end if completion.unpinRequested then if pinned[tostring(completion.unpinId)] and os.clock() - completion.unpinRequestedAt < 5 then return false end completion.unpinRequested = false end if not canSendAutomaticAction() then return false end local ok, err = pcall(Networking.Fire, "PinAccessory", unpinId, false) if not ok then warn("[MWG] could not unpin recipe to make room:", err) return false end completion.unpinRequested = true completion.unpinId = unpinId completion.unpinRequestedAt = os.clock() noteNetworkAction() lastAction = "Unpinned recipe to make room for the next one" return true end if not canSendAutomaticAction() then return false end local ok, err = pcall(Networking.Fire, "PinAccessory", completion.targetId, true) if not ok then warn("[MWG] could not pin next recipe:", err) return false end completion.awaitingPin = true completion.requestedAt = os.clock() noteNetworkAction() lastAction = "Pinned next recipe: " .. tostring(Translator.Get("Accessories." .. tostring(completion.targetId) .. ".1.Name")) return true end local function stepCraft() local planCount = #readyCraftPlans if not S.AutoCraft or planCount == 0 or not canSendAutomaticAction() then return false end if nextCraftPlanIndex > planCount then nextCraftPlanIndex = 1 end local plan = readyCraftPlans[nextCraftPlanIndex] nextCraftPlanIndex = nextCraftPlanIndex % planCount + 1 local attempt = craftAttempts[plan.accessoryId] local alreadyAttempted = attempt and attempt.level == plan.level and os.clock() - attempt.time < 15 if alreadyAttempted then return false end craftAttempts[plan.accessoryId] = { level = plan.level, time = os.clock() } local ok, err = pcall(Networking.Fire, "CraftAccessory", plan.accessoryId) if not ok then warn("[MWG] native craft request failed for " .. tostring(plan.accessoryId) .. ":", err) return false end noteNetworkAction() lastAction = string.format("Requested native craft for %s", plan.name) return true end local lobbyActions = homeTab:AddSection("Available Lobbies", false) local teleportingToLobby = false local lobbyInfo = GD.LobbyInfo local function canTeleportToLobby(depth) return depth <= data.NumberValues.HighestDepth.Value and data.NumberValues.LowestDepth.Value <= depth + 10 end for depth = lobbyInfo.Highest, lobbyInfo.Lowest, -lobbyInfo.Step do local targetDepth = depth FuncsV3:Button(lobbyActions, "Lobby at " .. tostring(targetDepth), "", function() if teleportingToLobby then return end if not canTeleportToLobby(targetDepth) then return end teleportingToLobby = true local ok, err = pcall(function() Networking.Fire("Teleport", targetDepth) end) if not ok then teleportingToLobby = false warn("[MWG] lobby teleport failed:", err) return end lastAction = string.format("Requested teleport to lobby %s", tostring(targetDepth)) task.delay(2, function() teleportingToLobby = false end) end) end local upgradeActions = homeTab:AddSection("Available Upgrades", false) for _, entry in ipairs(upgradeScreens) do FuncsV3:Button(upgradeActions, entry.title, "", function() if not gameFrames:FindFirstChild(entry.frame) then warn("[MWG] upgrade screen is unavailable:", entry.frame) return end local ok, err = pcall(GuiHandler, entry.frame, 1) if not ok then warn("[MWG] could not open upgrade screen " .. entry.frame .. ":", err) return end end) end local visualSection = homeTab:AddSection("Visual Options", false) FuncsV3:Toggle( visualSection, "Hide Explosive Effects", "Hide the local explosion visual when explosives are activated", S.HideExplosiveEffects, setExplosiveEffectsHidden ) local upgradesPage = new("Frame", { Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0), BackgroundTransparency = 1, Visible = false, }, body) label(upgradesPage, { Text = "Upgrade screens", Font = Enum.Font.GothamBold, TextSize = 15, Size = UDim2.new(1, 0, 0, 20), Position = UDim2.fromOffset(0, 0), }) local upgradesHint = label(upgradesPage, { Text = "Open the game's native upgrade screen. Emerald upgrades are not included.", TextSize = 11, TextColor3 = C.muted, TextWrapped = true, Size = UDim2.new(1, 0, 0, 32), Position = UDim2.fromOffset(0, 24), }) local upgradeList = new("ScrollingFrame", { Size = UDim2.new(1, 0, 0, PAGE_HEIGHT - 68), Position = UDim2.fromOffset(0, 62), BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5, CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y, }, upgradesPage) new("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder }, upgradeList) for order, entry in ipairs(upgradeScreens) do local button = new("TextButton", { Size = UDim2.new(1, -8, 0, 34), BackgroundColor3 = C.card, BorderSizePixel = 0, Text = entry.title, TextColor3 = C.text, Font = Enum.Font.GothamMedium, TextSize = 12, AutoButtonColor = false, LayoutOrder = order, }, upgradeList) corner(button, 7) outline(button, 0.93) track(button.MouseButton1Click:Connect(function() if not gameFrames:FindFirstChild(entry.frame) then upgradesHint.Text = entry.title .. " is not available in this game version." warn("[MWG] upgrade screen is unavailable:", entry.frame) return end local ok, err = pcall(GuiHandler, entry.frame, 1) if not ok then upgradesHint.Text = "Could not open " .. entry.title .. ". See console for details." warn("[MWG] could not open upgrade screen " .. entry.frame .. ":", err) return end upgradesHint.Text = "Opened " .. entry.title .. "." end)) end local pages = { main = { page = mainPage, tab = mainTab }, teleports = { page = teleportPage, tab = teleportsTab }, upgrades = { page = upgradesPage, tab = upgradesTab }, } local pageTransition local pageBodyTransition local pageTransitionId = 0 local function selectPage(page, animate) local selectedPage = pages[page] if not selectedPage then return end pageTransitionId += 1 local transitionId = pageTransitionId if pageTransition then pageTransition:Cancel() pageTransition = nil end if pageBodyTransition then pageBodyTransition:Cancel() pageBodyTransition = nil end local currentWindowHeight = win.AbsoluteSize.Y local currentBodyHeight = body.AbsoluteSize.Y win.AutomaticSize = Enum.AutomaticSize.None win.Size = UDim2.new(0, 420, 0, currentWindowHeight) body.AutomaticSize = Enum.AutomaticSize.None body.Size = UDim2.new(1, 0, 0, currentBodyHeight) for name, entry in pairs(pages) do local selected = name == page entry.page.Visible = selected entry.tab.BackgroundColor3 = selected and C.accent or C.off entry.tab.TextColor3 = C.text end body.AutomaticSize = Enum.AutomaticSize.Y if not animate or currentWindowHeight <= 0 then win.AutomaticSize = Enum.AutomaticSize.Y body.Size = UDim2.new(1, 0, 0, 0) body.AutomaticSize = Enum.AutomaticSize.Y return end body.ClipsDescendants = true task.spawn(function() RunService.Heartbeat:Wait() if transitionId ~= pageTransitionId then return end local targetBodyHeight = body.AbsoluteSize.Y body.AutomaticSize = Enum.AutomaticSize.None body.Size = UDim2.new(1, 0, 0, currentBodyHeight) local targetWindowHeight = 80 + targetBodyHeight pageTransition = tween(win, 0.28, { Size = UDim2.new(0, 420, 0, targetWindowHeight), }) pageBodyTransition = tween(body, 0.28, { Size = UDim2.new(1, 0, 0, targetBodyHeight), }) pageTransition.Completed:Connect(function(playbackState) if transitionId ~= pageTransitionId then return end pageTransition = nil pageBodyTransition = nil if playbackState == Enum.PlaybackState.Completed then body.Size = UDim2.new(1, 0, 0, 0) body.AutomaticSize = Enum.AutomaticSize.Y body.ClipsDescendants = false win.Size = UDim2.fromOffset(420, 0) win.AutomaticSize = Enum.AutomaticSize.Y end end) pageBodyTransition.Completed:Connect(function(playbackState) if playbackState == Enum.PlaybackState.Completed and transitionId == pageTransitionId then body.Size = UDim2.new(1, 0, 0, targetBodyHeight) end end) end) end track(mainTab.MouseButton1Click:Connect(function() selectPage("main", true) end)) track(teleportsTab.MouseButton1Click:Connect(function() selectPage("teleports", true) end)) track(upgradesTab.MouseButton1Click:Connect(function() selectPage("upgrades", true) end)) selectPage("main", false) local lobbyTeleports = {} for depth = lobbyInfo.Highest, lobbyInfo.Lowest, -lobbyInfo.Step do local targetDepth = depth local button = new("TextButton", { Size = UDim2.new(1, -8, 0, 34), BackgroundColor3 = C.card, BorderSizePixel = 0, Text = "", TextColor3 = C.text, Font = Enum.Font.GothamMedium, TextSize = 12, AutoButtonColor = false, LayoutOrder = #lobbyTeleports + 1, }, lobbyList) corner(button, 7) outline(button, 0.93) lobbyTeleports[#lobbyTeleports + 1] = { depth = targetDepth, button = button } track(button.MouseButton1Click:Connect(function() if teleportingToLobby or not canTeleportToLobby(targetDepth) then return end teleportingToLobby = true local ok, err = pcall(function() Networking.Fire("Teleport", targetDepth) end) if not ok then teleportingToLobby = false warn("[MWG] lobby teleport failed:", err) return end lastAction = string.format("Requested teleport to lobby %s", tostring(targetDepth)) task.delay(2, function() teleportingToLobby = false end) end)) end local function refreshLobbyButtons() for _, entry in ipairs(lobbyTeleports) do local unlocked = canTeleportToLobby(entry.depth) entry.button.Active = unlocked entry.button.TextColor3 = unlocked and C.text or C.muted entry.button.BackgroundColor3 = unlocked and C.card or C.track entry.button.Text = unlocked and string.format("Lobby at %s", tostring(entry.depth)) or string.format("Lobby at %s · Undiscovered", tostring(entry.depth)) end end refreshLobbyButtons() local mainLayoutOrder = 0 local autoBuyExpanded = true local autoBuyCards = {} local autoBuySection for order, item in ipairs(ITEMS) do if item.cat == "Luck" then mainLayoutOrder += 1 autoBuySection = new("TextButton", { Text = "Auto Buy (Luck, Jump, Speed) −", Font = Enum.Font.GothamBold, TextSize = 13, TextColor3 = C.accent, TextXAlignment = Enum.TextXAlignment.Left, Size = UDim2.new(1, -4, 0, 28), BackgroundColor3 = C.card, AutoButtonColor = false, BorderSizePixel = 0, LayoutOrder = mainLayoutOrder, }, mainPage) corner(autoBuySection, 7) new("UIPadding", { PaddingLeft = UDim.new(0, 10) }, autoBuySection) end mainLayoutOrder += 1 local card = new("Frame", { Size = UDim2.new(1, 0, 0, 86), BackgroundColor3 = C.card, BorderSizePixel = 0, LayoutOrder = mainLayoutOrder, }, mainPage) corner(card, 10) outline(card, 0.93) addSurfaceGradient(card) local ui = { card = card } ui.name = label(card, { Text = item.title, Font = Enum.Font.GothamBold, TextSize = 15, Size = UDim2.fromOffset(150, 20), Position = UDim2.fromOffset(14, 10), }) ui.sub = label(card, { TextSize = 12, TextColor3 = C.muted, Size = UDim2.fromOffset(180, 16), Position = UDim2.fromOffset(14, 31), }) makeSwitch(card, UDim2.fromOffset(218, 12), function() return S[item.cat] end, function(v) S[item.cat] = v end) ui.amount = label(card, { TextSize = 12, TextXAlignment = Enum.TextXAlignment.Right, Size = UDim2.new(1, -28, 0, 14), Position = UDim2.fromOffset(14, 50), }) local track_ = new("Frame", { Size = UDim2.new(1, -28, 0, 6), Position = UDim2.fromOffset(14, 68), BackgroundColor3 = C.track, BorderSizePixel = 0, }, card) corner(track_, 3) ui.fill = new("Frame", { Size = UDim2.fromScale(0, 1), BackgroundColor3 = C.accent, BorderSizePixel = 0 }, track_) corner(ui.fill, 3) item.ui = ui if item.cat == "Luck" or item.cat == "Jump" or item.cat == "Speed" then autoBuyCards[#autoBuyCards + 1] = card end end track(autoBuySection.MouseButton1Click:Connect(function() autoBuyExpanded = not autoBuyExpanded autoBuySection.Text = "Auto Buy (Luck, Jump, Speed) " .. (autoBuyExpanded and "−" or "+") for _, card in ipairs(autoBuyCards) do card.Visible = autoBuyExpanded end end)) mainLayoutOrder += 1 local footerOrder = mainLayoutOrder + 1 local footer = new("Frame", { Size = UDim2.new(1, 0, 0, 34), BackgroundTransparency = 1, LayoutOrder = footerOrder }, mainPage) local lastLbl = label(footer, { Text = "Waiting for cash…", TextSize = 12, Size = UDim2.new(1, 0, 0, 16), Position = UDim2.fromOffset(2, 0), }) label(footer, { Text = "RightShift hides · drag the title to move", TextSize = 10, TextColor3 = C.muted, Size = UDim2.new(1, 0, 0, 14), Position = UDim2.fromOffset(2, 19), }) -- live refresh -------------------------------------------------------- local function refresh() if gui.Enabled then for _, item in ipairs(ITEMS) do local ui = item.ui local def, ul, wallet = parts(item.cat) local enabled = S.master and S[item.cat] ui.name.TextColor3 = enabled and C.text or C.muted ui.card.BackgroundTransparency = S.master and 0 or 0.45 if not (def and ul and wallet) then ui.sub.Text = "Unavailable" else local lvl, have = ul.Value, wallet.Value if def.MaxLevel and lvl >= def.MaxLevel then ui.sub.Text = string.format("Level %d · max", lvl) ui.amount.Text = "Maxed out" if ui.fillTarget ~= 1 or ui.fillColor ~= C.muted then ui.fillTarget, ui.fillColor = 1, C.muted tween(ui.fill, 0.25, { Size = UDim2.fromScale(1, 1), BackgroundColor3 = C.muted }) end else local ok, cost = pcall(FH.GetEquipableCostForMultiple, data, item.cat, 1) ui.sub.Text = string.format("Level %d → %d", lvl, lvl + 1) if ok and type(cost) == "number" then ui.amount.Text = abbr(have) .. " / " .. abbr(cost) local frac = cost > 0 and math.clamp(have / cost, 0, 1) or 1 local fillColor = (have >= cost) and C.ok or C.accent if ui.fillTarget ~= frac or ui.fillColor ~= fillColor then ui.fillTarget, ui.fillColor = frac, fillColor tween(ui.fill, 0.25, { Size = UDim2.fromScale(frac, 1), BackgroundColor3 = fillColor }) end end end end end if not S.master then lastLbl.Text = "Paused" lastLbl.TextColor3 = C.muted elseif lastAction then lastLbl.Text = lastAction lastLbl.TextColor3 = C.text else lastLbl.Text = "Waiting for cash…" lastLbl.TextColor3 = C.muted end refreshLobbyButtons() end end -- drag -------------------------------------------------------------- local dragging, dragStart, startPos dragArea.InputBegan:Connect(function(i) if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then dragging, dragStart, startPos = true, i.Position, win.Position end end) track(UIS.InputChanged:Connect(function(i) if dragging and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then local d = i.Position - dragStart win.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + d.X, startPos.Y.Scale, startPos.Y.Offset + d.Y) end end)) track(UIS.InputEnded:Connect(function(i) if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then dragging = false end end)) -- collapse / hide / unload --------------------------------------------- local collapsed = false local expandedBodyHeight local collapseTween collapseBtn.MouseButton1Click:Connect(function() if collapseTween then collapseTween:Cancel() collapseTween = nil end if not collapsed then expandedBodyHeight = body.AbsoluteSize.Y body.AutomaticSize = Enum.AutomaticSize.None body.Size = UDim2.new(1, 0, 0, expandedBodyHeight) body.ClipsDescendants = true collapsed = true collapseBtn.Text = "+" collapseTween = tween(body, 0.28, { Size = UDim2.new(1, 0, 0, 0) }) collapseTween.Completed:Connect(function(playbackState) if playbackState == Enum.PlaybackState.Completed and collapsed then body.Visible = false collapseTween = nil end end) else collapsed = false local currentHeight = body.AbsoluteSize.Y body.Visible = true body.AutomaticSize = Enum.AutomaticSize.None body.Size = UDim2.new(1, 0, 0, currentHeight) body.ClipsDescendants = true collapseBtn.Text = "–" collapseTween = tween(body, 0.28, { Size = UDim2.new(1, 0, 0, expandedBodyHeight or 0), }) collapseTween.Completed:Connect(function(playbackState) if playbackState == Enum.PlaybackState.Completed and not collapsed then body.AutomaticSize = Enum.AutomaticSize.Y body.Size = UDim2.new(1, 0, 0, 0) body.ClipsDescendants = false collapseTween = nil end end) end end) track(UIS.InputBegan:Connect(function(i) if i.KeyCode == Enum.KeyCode.RightShift and not UIS:GetFocusedTextBox() and libraryWindowGui then libraryWindowGui.Enabled = not libraryWindowGui.Enabled end end)) local running = true closeBtn.MouseButton1Click:Connect(function() if env.__MWG_UNLOAD then env.__MWG_UNLOAD() end end) env.__MWG_UNLOAD = function() running = false restoreEmeraldTargeting() pageTransitionId += 1 if pageTransition then pageTransition:Cancel() pageTransition = nil end if pageBodyTransition then pageBodyTransition:Cancel() pageBodyTransition = nil end if collapseTween then collapseTween:Cancel() collapseTween = nil end for _, c in ipairs(conns) do pcall(function() c:Disconnect() end) end pcall(function() gui:Destroy() end) for _, libraryGui in ipairs(libraryGuis) do if libraryGui.Parent then libraryGui:Destroy() end end libraryGuis = {} env.__MWG_UNLOAD = nil env.__MWG_DECIDE = nil print("[MWG] Auto Buy unloaded") end ---------------------------------------------------------------------- -- Loops ---------------------------------------------------------------------- task.spawn(function() local tick = 0 while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do task.wait(0.4) if S.master then local pinOk, pinSent = pcall(stepPinNextRecipe) if not pinOk then warn("[MWG] auto-pin error:", pinSent) pinSent = false end if not pinSent then tick += 1 local ok, err = pcall(step, tick) if not ok then warn("[MWG] step error:", err) end local craftOk, craftErr = pcall(stepCraft) if not craftOk then warn("[MWG] auto-craft error:", craftErr) end end end end end) task.spawn(function() while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do local ok, err = pcall(refreshCraftReadout) if not ok then warn("[MWG] recipe scan error:", err) end task.wait(0.25) end end) task.spawn(function() while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do local ok, err = pcall(refresh) if not ok then warn("[MWG] refresh error:", err) end task.wait(2) end end) task.spawn(function() while running and SpeedHubLibrary and not SpeedHubLibrary.Unloaded do task.wait(0.25) end if running and SpeedHubLibrary and SpeedHubLibrary.Unloaded and env.__MWG_UNLOAD then env.__MWG_UNLOAD() end end) print("[MWG] Auto Buy loaded with Speed Hub X UI")