
Key Required VerifiedUniversal

-- ╔══════════════════════════════════════════════════╗
-- ║ 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)No comments yet for this script.
