-- ╔══════════════════════════════════════════════════╗ -- ║ Airport Tycoon Manager v4.0 ║ -- ║ by buildermEn — refactored by ENI ║ -- ╚══════════════════════════════════════════════════╝ -- Services local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") local VirtualUser = game:GetService("VirtualUser") local ReplicatedStorage = game:GetService("ReplicatedStorage") local player = Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local hrp = character:WaitForChild("HumanoidRootPart") -- Character respawn handler local savedWalkSpeed = 16 local function onCharacterAdded(newCharacter) character = newCharacter hrp = newCharacter:WaitForChild("HumanoidRootPart") -- Reapply walk speed local humanoid = newCharacter:WaitForChild("Humanoid") if humanoid and savedWalkSpeed ~= 16 then humanoid.WalkSpeed = savedWalkSpeed end end player.CharacterAdded:Connect(onCharacterAdded) -- Runtime discovery local runtime = Workspace:WaitForChild("AirportTycoonClientRuntime") local tycoonNumber = nil for _, v in ipairs(runtime:GetChildren()) do if v.Name ~= "Guide" and v.Name ~= "Planes" and v.Name ~= "TycoonTemplate" then tycoonNumber = v.Name break end end if not tycoonNumber then warn("[ATM v4] Tycoon not found!") return end local buttonFolder = runtime[tycoonNumber]:WaitForChild("Buttons") local leaderstats = player:WaitForChild("leaderstats") local moneyStat = leaderstats:WaitForChild("Money") -- Upgrade remote local Event = ReplicatedStorage .Packages ._Index["leifstout_networker@0.3.1"] .networker ._remotes .Upgrades .RemoteEvent -- Passengers remote (for starting security lane operations) local PassengerEvent = ReplicatedStorage .Packages ._Index["leifstout_networker@0.3.1"] .networker ._remotes .Passengers .RemoteEvent -- ── State ────────────────────────────────────────── local toggles = { autoCollect = false, autoTrash = false, autoBuy = false, autoRebirth = false, antiAfk = false, autoUpgrade = false, autoOps = false, } local config = { collectDelay = 0.3, trashDelay = 0.5, buyDelay = 0.5, rebirthDelay = 2, upgradeDelay = 5, upgradeFireCount = 4, opsDelay = 2, buyStrategy = "Smart", } local stats = { money = 0, rebirthCost = 0, totalUpgrades = 0, upgradesAttempted = 0, itemsBought = 0, trashCollected = 0, sessionStart = os.clock(), } -- ── Color Constants for Smart Mode ───────────────── -- Royal Purple = money-making buildings (priority 1) -- Bright Blue = security & checkin desks (priority 2) local ROYAL_PURPLE = BrickColor.new("Royal purple") local BRIGHT_BLUE = BrickColor.new("Bright blue") -- ╔══════════════════════════════════════════════════╗ -- ║ UTILITIES ║ -- ╚══════════════════════════════════════════════════╝ local function formatMoney(n) if n >= 1e9 then return string.format("%.2fB", n / 1e9) elseif n >= 1e6 then return string.format("%.2fM", n / 1e6) elseif n >= 1e3 then return string.format("%.1fK", n / 1e3) end return tostring(math.floor(n)) end local function formatUptime(seconds) local h = math.floor(seconds / 3600) local m = math.floor((seconds % 3600) / 60) local s = math.floor(seconds % 60) return string.format("%02d:%02d:%02d", h, m, s) end local function getHRP() local char = player.Character if not char then return nil end return char:FindFirstChild("HumanoidRootPart") end --- Classify a button's priority based on its Touch part color local function getButtonPriority(button) local touch = button:FindFirstChild("Touch") if not touch or not touch:IsA("BasePart") then return 3 end local brick = touch.BrickColor if brick == ROYAL_PURPLE then return 1 -- money makers first elseif brick == BRIGHT_BLUE then return 2 -- security / checkin second end return 3 -- everything else last end --- Returns purchasable buttons sorted by current strategy local function getButtons() local validButtons = {} for _, child in ipairs(buttonFolder:GetChildren()) do local devProduct = child:GetAttribute("DevProductId") local gamepass = child:GetAttribute("GamepassId") if (devProduct == 0 or devProduct == nil) and (gamepass == 0 or gamepass == nil) then local touch = child:FindFirstChild("Touch") if touch then table.insert(validButtons, child) end end end if config.buyStrategy == "Smart" then -- Sort by priority tier first, then cheapest within each tier table.sort(validButtons, function(a, b) local prioA = getButtonPriority(a) local prioB = getButtonPriority(b) if prioA ~= prioB then return prioA < prioB end local costA = a:GetAttribute("Cost") or math.huge local costB = b:GetAttribute("Cost") or math.huge return costA < costB end) elseif config.buyStrategy == "Most Expensive First" then table.sort(validButtons, function(a, b) local costA = a:GetAttribute("Cost") or math.huge local costB = b:GetAttribute("Cost") or math.huge return costA > costB end) else -- Cheapest First table.sort(validButtons, function(a, b) local costA = a:GetAttribute("Cost") or math.huge local costB = b:GetAttribute("Cost") or math.huge return costA < costB end) end return validButtons end local function getRebirthRequirement() local ok, result = pcall(function() local playerGui = player:WaitForChild("PlayerGui", 5) if not playerGui then return math.huge end -- Exact path: PlayerGui.UI.Menus.Rebirth.Requirements.Details.Money local ui = playerGui:FindFirstChild("UI") if not ui then return math.huge end local menus = ui:FindFirstChild("Menus") if not menus then return math.huge end local rebirth = menus:FindFirstChild("Rebirth") if not rebirth then return math.huge end local requirements = rebirth:FindFirstChild("Requirements") if not requirements then return math.huge end local details = requirements:FindFirstChild("Details") if not details then return math.huge end local moneyLabel = details:FindFirstChild("Money") if not moneyLabel then return math.huge end -- Format: "Price: $currentCash/$225K" -- We want the number after the / local text = moneyLabel.Text local required = text:match("/(%$[%d%.]+[KMBkmb]?)") if not required then return math.huge end -- Strip the $ sign required = required:gsub("%$", "") local num = tonumber(required:match("([%d%.]+)")) or 0 local suffix = required:upper():match("([KMB])") or "" if suffix == "K" then num = num * 1e3 elseif suffix == "M" then num = num * 1e6 elseif suffix == "B" then num = num * 1e9 end return num end) return ok and result or math.huge end -- ── Upgrade System (Proximity Prompt based) ──────── local upgradePrompts = {} -- { { prompt = ProximityPrompt, id = string, modelName = string } } local function refreshUpgradePrompts() upgradePrompts = {} pcall(function() local Models = runtime[tycoonNumber]:WaitForChild("Models", 5) if not Models then return end for _, descendant in pairs(Models:GetDescendants()) do if descendant:IsA("ProximityPrompt") and descendant.ActionText == "View Upgrades" then local id = string.gsub(descendant.ObjectText, " ", "") table.insert(upgradePrompts, { prompt = descendant, id = id, }) end end end) stats.totalUpgrades = #upgradePrompts return #upgradePrompts end local function doUpgradePass() if not toggles.autoUpgrade then return 0 end if #upgradePrompts == 0 then return 0 end local fired = 0 for _, entry in ipairs(upgradePrompts) do if not toggles.autoUpgrade then break end for i = 1, config.upgradeFireCount do pcall(function() Event:FireServer("requestUpgrade", tycoonNumber, entry.id) end) fired += 1 stats.upgradesAttempted += 1 end end return fired end -- ╔══════════════════════════════════════════════════╗ -- ║ UI SETUP ║ -- ╚══════════════════════════════════════════════════╝ local WindUI = loadstring(game:HttpGet( "https://github.com/Footagesus/WindUI/releases/latest/download/main.lua" ))() local Window = WindUI:CreateWindow({ Title = "Airport Tycoon Manager", Icon = "plane", Author = "by buildermEn", Folder = "AirportTycoon", Size = UDim2.fromOffset(580, 490), Theme = "Dark", Transparent = true, SideBarWidth = 200, HideSearchBar = true, ScrollBarEnabled = true, Acrylic = true, TabTransition = true, User = { Enabled = true, Anonymous = true, }, OpenButton = { Title = "ATM v4", CornerRadius = UDim.new(1, 0), StrokeThickness = 2, Enabled = true, Color = ColorSequence.new( Color3.fromRGB(85, 170, 255), Color3.fromRGB(0, 255, 127) ), }, }) local function notify(title, content, icon, duration) pcall(function() WindUI:Notify({ Title = title, Content = content or "", Icon = icon or "info", Duration = duration or 3, }) end) end -- ── Sections & Tabs ──────────────────────────────── local MainSection = Window:Section({ Title = "Main", Opened = true }) local ToolsSection = Window:Section({ Title = "Tools", Opened = true }) local InfoSection = Window:Section({ Title = "Info", Opened = true }) local HomeTab = MainSection:Tab({ Title = "Home", Icon = "home" }) local AutoTab = MainSection:Tab({ Title = "Automation", Icon = "robot" }) local UpgradesTab = ToolsSection:Tab({ Title = "Upgrades", Icon = "arrow-up-circle" }) local ExtrasTab = ToolsSection:Tab({ Title = "Extras", Icon = "wrench" }) local StatsTab = InfoSection:Tab({ Title = "Statistics", Icon = "bar-chart" }) local SettingsTab = InfoSection:Tab({ Title = "Settings", Icon = "settings-2" }) -- ╔══════════════════════════════════════════════════╗ -- ║ HOME TAB ║ -- ╚══════════════════════════════════════════════════╝ HomeTab:Paragraph({ Title = "Welcome to ATM v4", Desc = "Airport Tycoon Manager — automate your airport empire.", Image = "plane", ImageSize = 24, Color = Color3.fromRGB(85, 170, 255), }) HomeTab:Divider() local homeMoneyParagraph = HomeTab:Paragraph({ Title = "Money: $0", Desc = "Loading..." }) local homeRebirthParagraph = HomeTab:Paragraph({ Title = "Rebirth Progress: 0%", Desc = "Calculating..." }) local homeUptimeParagraph = HomeTab:Paragraph({ Title = "Session Uptime: 00:00:00", Desc = "" }) HomeTab:Divider() HomeTab:Paragraph({ Title = "Smart Buy Mode", Desc = "Prioritizes Royal Purple buttons (money makers) first, then Bright Blue (security/checkin), then everything else. Enable it in Automation.", Image = "zap", ImageSize = 18, Color = Color3.fromRGB(255, 200, 50), }) -- ╔══════════════════════════════════════════════════╗ -- ║ AUTOMATION TAB ║ -- ╚══════════════════════════════════════════════════╝ AutoTab:Section({ Title = "Income", Icon = "coins" }) AutoTab:Toggle({ Title = "Auto Collect ATM", Icon = "banknote", Desc = "Collects money from ATMs automatically", Value = false, Callback = function(state) toggles.autoCollect = state if state then notify("Auto Collect", "ATM collection enabled", "banknote") task.spawn(function() while toggles.autoCollect do task.wait(config.collectDelay) local charHrp = getHRP() if not charHrp then continue end local accumulators = Workspace:FindFirstChild("AirportTycoonAccumulatorTouches") if not accumulators then continue end for _, v in ipairs(accumulators:GetChildren()) do if v:IsA("BasePart") and v:FindFirstChild("TouchInterest") then pcall(function() firetouchinterest(charHrp, v, 0) firetouchinterest(charHrp, v, 1) end) end end end end) end end }) AutoTab:Slider({ Title = "Collect Speed", Desc = "Delay between cycles (s)", Value = { Min = 0.1, Max = 2, Default = 0.3 }, Callback = function(v) config.collectDelay = v end, }) AutoTab:Toggle({ Title = "Auto Pickup Trash", Icon = "trash-2", Desc = "Teleports to trash and collects it", Value = false, Callback = function(state) toggles.autoTrash = state if state then notify("Auto Trash", "Trash collection enabled", "trash-2") task.spawn(function() while toggles.autoTrash do task.wait(config.trashDelay) local trashFolder = Workspace:FindFirstChild("AirportTycoonTrash") if not trashFolder then continue end for _, child in ipairs(trashFolder:GetChildren()) do if not toggles.autoTrash then break end if #child:GetChildren() == 0 then continue end local sphere = child:FindFirstChild("Sphere") if not sphere then continue end local prompt = sphere:FindFirstChild("CleanTrashPrompt") if not prompt or not prompt:IsA("ProximityPrompt") then continue end local charHrp = getHRP() if not charHrp then continue end local originalCFrame = charHrp.CFrame pcall(function() charHrp.CFrame = sphere.CFrame + Vector3.new(0, 3, 0) task.wait(0.1) fireproximityprompt(prompt) task.wait(0.2) charHrp.CFrame = originalCFrame end) stats.trashCollected += 1 end end end) end end }) AutoTab:Slider({ Title = "Trash Speed", Desc = "Delay between cycles (s)", Value = { Min = 0.2, Max = 3, Default = 0.5 }, Callback = function(v) config.trashDelay = v end, }) AutoTab:Section({ Title = "Purchasing", Icon = "shopping-cart" }) AutoTab:Toggle({ Title = "Auto Buy Buttons", Icon = "shopping-bag", Desc = "Purchases available buttons automatically", Value = false, Callback = function(state) toggles.autoBuy = state if state then notify("Auto Buy", "Purchasing: " .. config.buyStrategy, "shopping-bag") task.spawn(function() while toggles.autoBuy do task.wait(config.buyDelay) local charHrp = getHRP() if not charHrp then continue end local availableButtons = getButtons() local boughtSomething = false for _, button in ipairs(availableButtons) do if not toggles.autoBuy then break end local currentMoney = moneyStat.Value local cost = button:GetAttribute("Cost") or math.huge if currentMoney >= cost then local touch = button:FindFirstChild("Touch") if touch and touch:FindFirstChild("TouchInterest") then pcall(function() firetouchinterest(charHrp, touch, 0) firetouchinterest(charHrp, touch, 1) end) boughtSomething = true stats.itemsBought += 1 task.wait(0.3) end end end if not boughtSomething then task.wait(1) end end end) end end }) AutoTab:Dropdown({ Title = "Buy Strategy", Desc = "How buttons are prioritized", Values = { "Smart", "Cheapest First", "Most Expensive First" }, Value = "Smart", Callback = function(selected) config.buyStrategy = selected notify("Strategy", "Buy order: " .. selected, "shuffle") end, }) AutoTab:Paragraph({ Title = "Smart Mode Priority", Desc = "1. Royal Purple (money makers)\n2. Bright Blue (security/checkin)\n3. Everything else\nCheapest first within each tier.", Image = "list-ordered", ImageSize = 16, Color = Color3.fromRGB(170, 85, 255), }) AutoTab:Section({ Title = "Rebirth", Icon = "refresh-cw" }) AutoTab:Toggle({ Title = "Auto Rebirth", Icon = "refresh-cw", Desc = "Rebirths when you can afford it", Value = false, Callback = function(state) toggles.autoRebirth = state if state then notify("Auto Rebirth", "Will rebirth when affordable", "refresh-cw") task.spawn(function() local RebirthEvent = ReplicatedStorage .Packages ._Index["leifstout_networker@0.3.1"] .networker ._remotes .Rebirths .RemoteEvent while toggles.autoRebirth do task.wait(config.rebirthDelay) local requirement = getRebirthRequirement() local currentMoney = moneyStat.Value if currentMoney >= requirement and requirement ~= math.huge then pcall(function() RebirthEvent:FireServer("requestRebirth") end) task.wait(1) -- Confirm it worked by checking if money dropped if moneyStat.Value < currentMoney then notify("Rebirth!", "Successfully rebirthed!", "refresh-cw", 5) task.wait(3) end end end end) end end }) AutoTab:Section({ Title = "Operations", Icon = "scan" }) AutoTab:Toggle({ Title = "Auto Start Security Lanes", Icon = "scan", Desc = "Engage → 10s work → 1s disengage for collections → recheck", Value = false, Callback = function(state) toggles.autoOps = state if state then -- Pause trash to avoid teleport conflicts toggles._trashWasOn = toggles.autoTrash if toggles.autoTrash then toggles.autoTrash = false notify("Auto Ops", "Trash paused while active", "pause") end notify("Auto Ops", "Monitoring security lanes", "scan") task.spawn(function() while toggles.autoOps do -- SCAN: find lanes with visible Caution warning local lanesToStart = {} pcall(function() local Models = runtime[tycoonNumber].Models for _, model in pairs(Models:GetChildren()) do if not model.Name:find("SecurityLane") then continue end local caution = nil pcall(function() caution = model.Level1.Core.Information.Caution end) if not caution then continue end local isVisible = false pcall(function() isVisible = caution.Visible end) if not isVisible then continue end -- Has visible warning — grab the interaction Part local targetPart = nil pcall(function() targetPart = model.Level1.Core.Part end) if targetPart then table.insert(lanesToStart, { name = model.Name, part = targetPart, }) end end end) if #lanesToStart > 0 then local charHrp = getHRP() if charHrp then local homeCFrame = charHrp.CFrame -- ENGAGE: teleport to each lane and fire its prompt for _, lane in ipairs(lanesToStart) do if not toggles.autoOps then break end pcall(function() charHrp.CFrame = lane.part.CFrame + Vector3.new(0, 3, 0) task.wait(0.2) for _, child in pairs(lane.part:GetChildren()) do if child:IsA("ProximityPrompt") then fireproximityprompt(child) break end end task.wait(0.2) end) pcall(function() PassengerEvent:FireServer( "requestStartOperation", tycoonNumber, lane.name ) end) end -- HOLD: stay engaged ~10 seconds local held = 0 while held < 10 and toggles.autoOps do task.wait(1) held += 1 end -- DISENGAGE: teleport home for 1s so auto-collect can fire if toggles.autoOps then pcall(function() charHrp = getHRP() if charHrp then charHrp.CFrame = homeCFrame end end) task.wait(1) -- collection window end end else -- No lanes need help, chill before next scan task.wait(config.opsDelay) end -- Loop back to SCAN — rechecks if any lanes still have issues end end) else -- Restore trash if it was on before if toggles._trashWasOn then toggles.autoTrash = true toggles._trashWasOn = false notify("Auto Ops", "Trash collection resumed", "play") task.spawn(function() while toggles.autoTrash do task.wait(config.trashDelay) local trashFolder = Workspace:FindFirstChild("AirportTycoonTrash") if not trashFolder then continue end for _, child in ipairs(trashFolder:GetChildren()) do if not toggles.autoTrash then break end if #child:GetChildren() == 0 then continue end local sphere = child:FindFirstChild("Sphere") if not sphere then continue end local prompt = sphere:FindFirstChild("CleanTrashPrompt") if not prompt or not prompt:IsA("ProximityPrompt") then continue end local charHrp = getHRP() if not charHrp then continue end local originalCFrame = charHrp.CFrame pcall(function() charHrp.CFrame = sphere.CFrame + Vector3.new(0, 3, 0) task.wait(0.1) fireproximityprompt(prompt) task.wait(0.2) charHrp.CFrame = originalCFrame end) stats.trashCollected += 1 end end end) end end end }) AutoTab:Slider({ Title = "Ops Check Delay", Desc = "Seconds between lane checks", Value = { Min = 0.5, Max = 10, Default = 2 }, Callback = function(v) config.opsDelay = v end, }) -- ╔══════════════════════════════════════════════════╗ -- ║ UPGRADES TAB (Proximity Prompt system) ║ -- ╚══════════════════════════════════════════════════╝ UpgradesTab:Section({ Title = "Auto Upgrade", Icon = "zap" }) UpgradesTab:Paragraph({ Title = "How It Works", Desc = "Scans your tycoon models for ProximityPrompts with ActionText 'View Upgrades'. Reads ObjectText (spaces stripped) as the upgrade ID, then fires requestUpgrade on the remote for each one.", Image = "arrow-up-circle", ImageSize = 18, Color = Color3.fromRGB(255, 170, 0), }) UpgradesTab:Toggle({ Title = "Auto Upgrade", Icon = "zap", Desc = "Continuously fires upgrade remotes every cycle", Value = false, Callback = function(state) toggles.autoUpgrade = state if state then notify("Auto Upgrade", "Running continuously", "zap") task.spawn(function() while toggles.autoUpgrade do refreshUpgradePrompts() if #upgradePrompts > 0 then local fired = doUpgradePass() end task.wait(config.upgradeDelay) end end) end end }) UpgradesTab:Slider({ Title = "Fires Per ID", Desc = "How many times to fire each upgrade ID per cycle", Value = { Min = 1, Max = 10, Default = 4 }, Callback = function(v) config.upgradeFireCount = v end, }) UpgradesTab:Slider({ Title = "Cycle Delay", Desc = "Seconds between each upgrade cycle", Value = { Min = 1, Max = 30, Default = 5 }, Callback = function(v) config.upgradeDelay = v end, }) UpgradesTab:Button({ Title = "Refresh Upgrade Prompts", Icon = "search", Desc = "Rescan for ComponentUpgradePrompt instances", Callback = function() local count = refreshUpgradePrompts() notify("Prompts Found", count .. " upgrade prompts detected", "search") end }) UpgradesTab:Button({ Title = "Run Single Pass Now", Icon = "play", Desc = "Fire upgrade remote for all discovered IDs once", Callback = function() refreshUpgradePrompts() if #upgradePrompts == 0 then notify("No Prompts", "No ComponentUpgradePrompt found", "alert-triangle") return end task.spawn(function() local upgraded = doUpgradePass() notify("Manual Pass", "Fired " .. upgraded .. " prompts", "check") end) end }) UpgradesTab:Section({ Title = "Detected Prompts", Icon = "activity" }) local upgradeCountParagraph = UpgradesTab:Paragraph({ Title = "Upgrade Prompts: 0", Desc = "Hit Refresh to scan", }) -- ╔══════════════════════════════════════════════════╗ -- ║ EXTRAS TAB ║ -- ╚══════════════════════════════════════════════════╝ ExtrasTab:Section({ Title = "UI Cleanup", Icon = "eye-off" }) ExtrasTab:Paragraph({ Title = "Remove Game UI", Desc = "Hide annoying popups and shop menus from the game's default interface.", }) ExtrasTab:Button({ Title = "Remove Currency Popups", Icon = "x-circle", Desc = "Hides PlayerGui.Currency.Popups", Callback = function() pcall(function() local currency = player.PlayerGui:FindFirstChild("Currency") if currency then local p = currency:FindFirstChild("Popups") if p then p:Destroy(); notify("Removed", "Currency Popups destroyed", "check") else notify("Not Found", "Popups not found inside Currency", "alert-triangle") end else notify("Not Found", "Currency GUI not found", "alert-triangle") end end) end }) ExtrasTab:Button({ Title = "Remove Shop Menu", Icon = "x-circle", Desc = "Hides PlayerGui.UI.Menus.Shop", Callback = function() pcall(function() local ui = player.PlayerGui:FindFirstChild("UI") if ui then local menus = ui:FindFirstChild("Menus") if menus then local shop = menus:FindFirstChild("Shop") if shop then shop:Destroy(); notify("Removed", "Shop menu destroyed", "check") else notify("Not Found", "Shop not found", "alert-triangle") end else notify("Not Found", "Menus folder not found", "alert-triangle") end else notify("Not Found", "UI GUI not found", "alert-triangle") end end) end }) ExtrasTab:Button({ Title = "Remove Both", Icon = "trash", Desc = "Currency Popups + Shop Menu at once", Callback = function() local removed = 0 pcall(function() local c = player.PlayerGui:FindFirstChild("Currency") if c then local p = c:FindFirstChild("Popups"); if p then p:Destroy(); removed += 1 end end end) pcall(function() local u = player.PlayerGui:FindFirstChild("UI") if u then local m = u:FindFirstChild("Menus") if m then local s = m:FindFirstChild("Shop"); if s then s:Destroy(); removed += 1 end end end end) notify("Cleanup", "Removed " .. removed .. "/2 elements", "check") end }) -- ╔══════════════════════════════════════════════════╗ -- ║ STATISTICS TAB ║ -- ╚══════════════════════════════════════════════════╝ StatsTab:Section({ Title = "Financial", Icon = "dollar-sign" }) local statMoney = StatsTab:Paragraph({ Title = "Money: $0", Desc = "" }) local statRebirthBar = StatsTab:ProgressBar({ Title = "Rebirth Progress", Desc = "How close to next rebirth", Value = { Min = 0, Max = 100, Default = 0 }, Format = function(v, pct) return string.format("%.1f%%", pct) end, }) local statRebirthCost = StatsTab:Paragraph({ Title = "Rebirth Cost: N/A", Desc = "" }) StatsTab:Section({ Title = "Session", Icon = "clock" }) local statUptime = StatsTab:Paragraph({ Title = "Uptime: 00:00:00", Desc = "" }) local statBought = StatsTab:Paragraph({ Title = "Items Bought: 0", Desc = "" }) local statTrash = StatsTab:Paragraph({ Title = "Trash Collected: 0", Desc = "" }) StatsTab:Section({ Title = "Upgrades", Icon = "trending-up" }) local statPrompts = StatsTab:Paragraph({ Title = "Upgrade Prompts: 0", Desc = "" }) local statUpgradesFired = StatsTab:Paragraph({ Title = "Upgrades Attempted: 0", Desc = "" }) -- ── Stats updater ────────────────────────────────── local function updateAllStats() stats.money = moneyStat.Value stats.rebirthCost = getRebirthRequirement() pcall(function() -- Home tab homeMoneyParagraph:SetTitle("Money: $" .. formatMoney(stats.money)) homeMoneyParagraph:SetDesc("Raw: " .. stats.money) local progress = 0 if stats.rebirthCost > 0 and stats.rebirthCost ~= math.huge then progress = math.min(100, (stats.money / stats.rebirthCost) * 100) end homeRebirthParagraph:SetTitle("Rebirth Progress: " .. math.floor(progress) .. "%") homeRebirthParagraph:SetDesc("Cost: $" .. (stats.rebirthCost == math.huge and "N/A" or formatMoney(stats.rebirthCost))) local uptime = os.clock() - stats.sessionStart homeUptimeParagraph:SetTitle("Session Uptime: " .. formatUptime(uptime)) -- Stats tab statMoney:SetTitle("Money: $" .. formatMoney(stats.money)) statMoney:SetDesc("Raw: " .. stats.money) statRebirthBar:Set(progress) statRebirthCost:SetTitle("Rebirth Cost: $" .. (stats.rebirthCost == math.huge and "N/A" or formatMoney(stats.rebirthCost))) statUptime:SetTitle("Uptime: " .. formatUptime(uptime)) statBought:SetTitle("Items Bought: " .. stats.itemsBought) statTrash:SetTitle("Trash Collected: " .. stats.trashCollected) statPrompts:SetTitle("Upgrade Prompts: " .. #upgradePrompts) statUpgradesFired:SetTitle("Upgrades Attempted: " .. stats.upgradesAttempted) -- Upgrades tab prompt count upgradeCountParagraph:SetTitle("Upgrade Prompts: " .. #upgradePrompts) upgradeCountParagraph:SetDesc(#upgradePrompts > 0 and "Ready to upgrade" or "No prompts found — hit Refresh") end) end -- ╔══════════════════════════════════════════════════╗ -- ║ SETTINGS TAB ║ -- ╚══════════════════════════════════════════════════╝ SettingsTab:Section({ Title = "Connection", Icon = "wifi" }) SettingsTab:Toggle({ Title = "Anti AFK", Icon = "shield", Desc = "Prevents being kicked for inactivity", Value = false, Callback = function(state) toggles.antiAfk = state if state then notify("Anti AFK", "AFK prevention enabled", "shield") task.spawn(function() while toggles.antiAfk do task.wait(120) if not toggles.antiAfk then break end pcall(function() VirtualUser:CaptureController() VirtualUser:ClickButton2(Vector2.new(0, 0)) end) end end) end end }) SettingsTab:Section({ Title = "Player Controls", Icon = "user" }) SettingsTab:Slider({ Title = "Walk Speed", Desc = "Default is 16", Value = { Min = 16, Max = 200, Default = 16 }, Callback = function(v) savedWalkSpeed = v pcall(function() local char = player.Character if char then local humanoid = char:FindFirstChildOfClass("Humanoid") if humanoid then humanoid.WalkSpeed = v end end end) end, }) -- Fly state local flying = false local flySpeed = 50 local flyBodyVelocity = nil local flyBodyGyro = nil SettingsTab:Toggle({ Title = "Flight", Icon = "wind", Desc = "Hold jump to fly, WASD to steer", Value = false, Callback = function(state) flying = state local char = player.Character if not char then return end local charHrp = char:FindFirstChild("HumanoidRootPart") local humanoid = char:FindFirstChildOfClass("Humanoid") if not charHrp or not humanoid then return end if state then -- Create flight movers flyBodyVelocity = Instance.new("BodyVelocity") flyBodyVelocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge) flyBodyVelocity.Velocity = Vector3.new(0, 0, 0) flyBodyVelocity.Parent = charHrp flyBodyGyro = Instance.new("BodyGyro") flyBodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge) flyBodyGyro.P = 9e4 flyBodyGyro.Parent = charHrp notify("Flight", "Enabled — use WASD + Space/Shift", "wind") task.spawn(function() local UIS = game:GetService("UserInputService") while flying do task.wait() if not flying then break end local cam = Workspace.CurrentCamera local moveDir = Vector3.new(0, 0, 0) if UIS:IsKeyDown(Enum.KeyCode.W) then moveDir = moveDir + cam.CFrame.LookVector end if UIS:IsKeyDown(Enum.KeyCode.S) then moveDir = moveDir - cam.CFrame.LookVector end if UIS:IsKeyDown(Enum.KeyCode.A) then moveDir = moveDir - cam.CFrame.RightVector end if UIS:IsKeyDown(Enum.KeyCode.D) then moveDir = moveDir + cam.CFrame.RightVector end if UIS:IsKeyDown(Enum.KeyCode.Space) then moveDir = moveDir + Vector3.new(0, 1, 0) end if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then moveDir = moveDir - Vector3.new(0, 1, 0) end if moveDir.Magnitude > 0 then moveDir = moveDir.Unit * flySpeed end flyBodyVelocity.Velocity = moveDir flyBodyGyro.CFrame = cam.CFrame end end) else -- Clean up flight movers if flyBodyVelocity then flyBodyVelocity:Destroy(); flyBodyVelocity = nil end if flyBodyGyro then flyBodyGyro:Destroy(); flyBodyGyro = nil end notify("Flight", "Disabled", "wind") end end }) SettingsTab:Slider({ Title = "Fly Speed", Desc = "How fast you fly", Value = { Min = 10, Max = 300, Default = 50 }, Callback = function(v) flySpeed = v end, }) SettingsTab:Section({ Title = "UI Controls", Icon = "sliders" }) SettingsTab:Keybind({ Title = "Toggle UI", Desc = "Show/hide the window", Value = "RightControl", Callback = function() pcall(function() Window:Toggle() end) end }) SettingsTab:Button({ Title = "Refresh Everything", Icon = "refresh-cw", Desc = "Reload buttons, prompts, and stats", Callback = function() refreshUpgradePrompts() updateAllStats() notify("Refreshed", "All data reloaded", "refresh-cw") end }) local DestroyDialog DestroyDialog = Window:Dialog({ Title = "Destroy UI", Icon = "alert-triangle", Content = "Close the script? All automation stops.", Buttons = { { Title = "Yes, Close", Variant = "Primary", Callback = function() for key, _ in pairs(toggles) do toggles[key] = false end Window:Destroy() end }, { Title = "Cancel", Callback = function() DestroyDialog:Close() end } } }) SettingsTab:Button({ Title = "Destroy UI", Icon = "x", Desc = "Close the script (with confirmation)", Callback = function() DestroyDialog:Show() end }) -- ╔══════════════════════════════════════════════════╗ -- ║ INIT ║ -- ╚══════════════════════════════════════════════════╝ refreshUpgradePrompts() updateAllStats() task.spawn(function() while task.wait(2) do pcall(updateAllStats) end end) notify("Script Loaded", "ATM v4 ready! Smart mode + prompt upgrades", "plane", 5)