ORBITAL — Mine a Planet

Code du script
-- ORBITAL - Mine a Planet [BETA 8]
if game.PlaceId ~= 121125129560252 then return end
local BOOTOK, BOOTERR = pcall(function()
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local RS = game:GetService("ReplicatedStorage")
local LP = Players.LocalPlayer
local Net = RS:WaitForChild("Net")
local HOST = (gethui and gethui()) or game:GetService("CoreGui")
for _, root in ipairs({ HOST, LP:FindFirstChild("PlayerGui") }) do
if root then for _, n in ipairs({ "Orbital", "OrbitalBoot" }) do
local o = root:FindFirstChild(n); if o then pcall(function() o:Destroy() end) end
end end
end
local DEF = { autoCollect=false, autoSell=false, autoUpgrade=false, autoEvent=false, autoRoll=false,
rarities = { Divine=true, Exotic=true, Prismatic=true, Transcendent=true, Void=true },
returnHome=true, notify=true, collectMs=140 }
local S = getgenv().OrbitalX
if not S then S = {}; getgenv().OrbitalX = S; for k,v in pairs(DEF) do S[k]=v end end
for k,v in pairs(DEF) do if S[k]==nil then S[k]=v end end
if S._cleanup then pcall(S._cleanup); task.wait(0.1) end
S.run = true
local GEN = (S._gen or 0)+1; S._gen = GEN
local function live() return S.run==true and S._gen==GEN end
-- stats can survive a hot reload from an older build, so backfill every field
local stats = S._stats or {}
stats.collected = stats.collected or 0
stats.upgrades = stats.upgrades or 0
stats.rolls = stats.rolls or 0
stats.errors = stats.errors or 0
S._stats = stats
local conns = {}
if getgenv()._OrbitalConns then for _,c in ipairs(getgenv()._OrbitalConns) do pcall(function() c:Disconnect() end) end end
getgenv()._OrbitalConns = {}
local function track(c) if c then conns[#conns+1]=c; table.insert(getgenv()._OrbitalConns,c) end return c end
-- theme
local C = { bg=Color3.fromRGB(12,14,20), surf=Color3.fromRGB(19,22,31), surf2=Color3.fromRGB(27,31,43),
line=Color3.fromRGB(60,70,96), txt=Color3.fromRGB(236,240,250), sub=Color3.fromRGB(132,144,172),
acc=Color3.fromRGB(96,170,255), good=Color3.fromRGB(80,214,140), bad=Color3.fromRGB(240,96,110) }
local FB,FM,FR = Enum.Font.GothamBold, Enum.Font.GothamMedium, Enum.Font.Gotham
local function mk(cls,p,k) local i=Instance.new(cls) for a,b in pairs(p) do i[a]=b end if k then for _,c in ipairs(k) do c.Parent=i end end return i end
local function corner(r) return mk("UICorner",{CornerRadius=UDim.new(0,r or 8)}) end
local function stroke(t,c) return mk("UIStroke",{Transparency=t or 0.8,Color=c or C.line,Thickness=1}) end
local function pad(n) return mk("UIPadding",{PaddingTop=UDim.new(0,n),PaddingBottom=UDim.new(0,n),PaddingLeft=UDim.new(0,n),PaddingRight=UDim.new(0,n)}) end
local function tw(o,p,t,st) TweenService:Create(o,TweenInfo.new(t or 0.18,st or Enum.EasingStyle.Quad,Enum.EasingDirection.Out),p):Play() end
-- ======================================================= root gui (hidden) =
local gui = mk("ScreenGui",{Name="Orbital",ResetOnSpawn=false,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,DisplayOrder=999,Enabled=false,Parent=HOST})
local toasts = mk("Frame",{AnchorPoint=Vector2.new(1,0),Position=UDim2.new(1,-18,0,18),Size=UDim2.new(0,300,1,-36),
BackgroundTransparency=1,Parent=gui},{mk("UIListLayout",{Padding=UDim.new(0,8),HorizontalAlignment=Enum.HorizontalAlignment.Right,SortOrder=Enum.SortOrder.LayoutOrder})})
local function notify(title,msg,kind)
if not S.notify then return end
local col=(kind=="bad" and C.bad) or (kind=="good" and C.good) or C.acc
local card=mk("Frame",{Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,BackgroundColor3=C.surf,
Position=UDim2.new(1,40,0,0),Parent=toasts},{corner(10),stroke(0.72)})
mk("Frame",{Size=UDim2.new(0,3,1,0),BackgroundColor3=col,BorderSizePixel=0,Parent=card})
local body=mk("Frame",{Position=UDim2.new(0,14,0,0),Size=UDim2.new(1,-24,0,0),AutomaticSize=Enum.AutomaticSize.Y,
BackgroundTransparency=1,Parent=card},{mk("UIPadding",{PaddingTop=UDim.new(0,10),PaddingBottom=UDim.new(0,11)}),
mk("UIListLayout",{Padding=UDim.new(0,2),SortOrder=Enum.SortOrder.LayoutOrder})})
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,15),Text=title,TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,LayoutOrder=1,Parent=body})
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,Text=msg,
TextColor3=C.sub,TextWrapped=true,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,LayoutOrder=2,Parent=body})
tw(card,{Position=UDim2.new(0,0,0,0)},0.28)
task.delay(5,function() if card.Parent then tw(card,{Position=UDim2.new(1,40,0,0)},0.25) task.wait(0.3) pcall(function() card:Destroy() end) end end)
end
S._notify=notify
local errLast, errLog = {}, {}
S._errLog=errLog
local function report(f,e)
stats.errors=stats.errors+1
local m=tostring(e):gsub("^.-:%d+: ",""):sub(1,110)
table.insert(errLog,1,{f=f,e=m,t=os.date("%H:%M:%S")}); if #errLog>30 then table.remove(errLog) end
local now=os.clock()
if not errLast[f] or now-errLast[f]>20 then errLast[f]=now; notify("Error: "..f,m,"bad") end
end
local function loopify(fn,delay,name)
task.spawn(function() while live() do
local ok,err=xpcall(fn,function(e) return tostring(e).." | "..debug.traceback("",2):gsub("%s+"," "):sub(1,160) end)
if not ok then report(name,err) end
task.wait((type(delay)=="function" and delay()) or delay)
end end)
end
-- ======================================================= game bindings ====
local function R(n) return Net:FindFirstChild(n) end
local MYID = LP.UserId
local function ownerOf(i) local a=i.Parent for _=1,6 do if not a then return end local v=a:GetAttribute("FS_UserId") if v then return v end a=a.Parent end end
local myDocks = {}
local function reindexDocks()
table.clear(myDocks)
for _,d in ipairs(workspace:GetDescendants()) do
if d:IsA("BasePart") and d:GetAttribute("FS_OreCount")~=nil and ownerOf(d)==MYID then
local pr=d:FindFirstChildWhichIsA("ProximityPrompt"); if pr then myDocks[d]=pr end
end
end
end
pcall(reindexDocks)
local function myOre() local t,n=0,0 for p in pairs(myDocks) do local ok,v=pcall(function() return p.Parent and p:GetAttribute("FS_OreCount") or nil end) if ok and v then t=t+v n=n+1 end end return t,n end
-- native perk toggles (player already owns these; this is the game's own path)
local function setPerk(key,val)
local r=R("SetAutoPerk"); if not r then return false end
local ok=pcall(function() r:FireServer({key=key,value=val}) end)
return ok
end
-- upgrade state cache
local UP = {
{k="luck", req="RequestUpgradeLuck", sync="LuckSync", label="Luck"},
{k="dockStorage", req="RequestUpgradeDockStorage", sync="DockStorageSync", label="Dock Storage"},
{k="laser", req="RequestUpgradeLaserPower", sync="LaserSync", label="Laser"},
{k="droneRolls", req="RequestUpgradeDroneRolls", sync="DroneRollSync", label="Drone Rolls"},
{k="planet", req="RequestUpgradePlanet", sync="PlanetSync", label="Planet"},
{k="cargo", req="RequestUpgradeCargo", sync="CargoSync", label="Cargo"},
}
local upState = {}
S._upState = upState
for _,u in ipairs(UP) do
local r=R(u.sync)
if r then track(r.OnClientEvent:Connect(function(payload)
local st=payload
if type(st)=="table" and st.nextCost==nil and st.level==nil then
for _,v in pairs(st) do if type(v)=="table" and (v.nextCost~=nil or v.level~=nil) then st=v break end end
end
upState[u.k]=st
end)) end
end
local cash=0
do local r=R("CurrencySync")
if r then track(r.OnClientEvent:Connect(function(p)
local s=p; if type(s)=="table" and s.m==nil then for _,v in pairs(s) do if type(v)=="table" and v.m then s=v break end end end
if type(s)=="table" and s.m then cash=(s.m or 0)*10^(s.e or 0) end
end)) end
end
local function pullState() pcall(function() local r=R("RequestStateSync") if r then r:FireServer() end end) end
pullState()
-- forward declared: the automation loops below are defined before the movement helpers
local hrpOf, flyTo, myEventDrops, mySellPad
-- ======================================================= event drops =====
-- Mirrors GlobalDropController's protocol exactly:
-- sync {campaignId, scope="server"|"global", drops={{dropId,position,expiresAt}}}
-- {clear=true, scope} -> wipe that scope
-- {claimResult={dropId,status,retryAfter}}
-- claim RequestGlobalDropClaim:FireServer{dropId, campaignId, scope}
-- The game gates claims client-side on distance (<=8 studs); we skip that and claim by id,
-- but we DO honour its 2s per-drop throttle, the retry backoff, and the server's
-- EventDropConfig.maxClaimsPerMinute = 90 cap so we never trip rate limiting.
local drops, claimTimes = {}, {}
local ev = S._ev or { claimed=0, rejected=0, attempts=0 }
S._ev = ev; S._drops = drops
local MAX_CLAIMS_PER_MIN = 85 -- config says 90; stay just under
do
local r = R("GlobalDropSync")
if r then track(r.OnClientEvent:Connect(function(p)
if type(p) ~= "table" then return end
if p.clear == true and (p.scope == "server" or p.scope == "global") then
for id, d in pairs(drops) do if d.scope == p.scope then drops[id] = nil end end
return
end
local cr = p.claimResult
if type(cr) == "table" and type(cr.dropId) == "string" then
if cr.status == "claimed" then drops[cr.dropId] = nil; ev.claimed = ev.claimed + 1
elseif cr.status == "terminal" then drops[cr.dropId] = nil; ev.rejected = ev.rejected + 1
elseif cr.status == "retry" then
local d = drops[cr.dropId]
if d then d.nextClaimAt = os.clock() + math.clamp(tonumber(cr.retryAfter) or 1, 0.5, 2) end
end
return
end
if type(p.campaignId) == "string" and (p.scope == "server" or p.scope == "global") and type(p.drops) == "table" then
for _, v in ipairs(p.drops) do
if type(v) == "table" and type(v.dropId) == "string" and typeof(v.position) == "Vector3" and drops[v.dropId] == nil then
drops[v.dropId] = { position = v.position, expiresAt = v.expiresAt,
campaignId = p.campaignId, scope = p.scope, nextClaimAt = 0 }
end
end
end
end)) end
end
local function dropCount() local n = 0 for _ in pairs(drops) do n = n + 1 end return n end
local function shards(kind) return LP:GetAttribute("FS_EventShards_" .. kind) or 0 end
-- Auto roll. The game's native SetAutoRollActive is gamepass gated (FS_GP_autoRoll), and the
-- server rejects it if unowned, so we drive the roll action itself instead. Targets are still
-- pushed so the native panel stays in sync if the pass is ever owned.
loopify(function()
if not S.autoRoll then return end
local r = R("RequestRollDrones"); if not r then return end
pcall(function() r:FireServer({}) end)
stats.rolls = (stats.rolls or 0) + 1
end, 1.1, "Auto roll")
-- Incident shard pickup is validated SERVER-SIDE (EventDropConfig.pickupRadiusStuds = 8) and
-- there is no client claim remote for it, so it cannot be done from range. What we can do is
-- park at the sky beam where drops spawn (radius 110 around FS_SkyBeamAnchor) - which is exactly
-- what any player farming the event does, so it reads as completely normal.
local function eventActive() return #myEventDrops() > 0 end
S._eventActive = eventActive
-- Fly over each of OUR drops. The server grants the shard on proximity (8 studs), which is
-- exactly the manual "fly over it" action, just driven automatically. Returns home after.
loopify(function()
if not S.autoEvent then return end
if not (S._myDrops and S._flyTo and S._hrpOf) then return end
local list = S._myDrops()
ev.pending = #list
if #list == 0 then return end
local hrp = S._hrpOf(); if not hrp then return end
local home = hrp.Position
for _, drop in ipairs(list) do
if not live() or not S.autoEvent then break end
if drop.Parent then
-- must close to ~3 studs: the server only grants the pickup on true contact range
local ok = S._flyTo(drop.Position, 3)
ev.moves = (ev.moves or 0) + 1
if ok then
task.wait(0.8) -- let the server register the pickup
if not drop.Parent then ev.claimed = ev.claimed + 1 end
end
end
end
if S.returnHome ~= false then S._flyTo(home, 6) end
end, 2.5, "Event shards")
-- Auto sell. The native autoSell perk is gamepass gated (FS_GP_autoSell) and the server refuses
-- to enable it when unowned, so we do it the manual way: fly to OUR sell pad (prompt range is 16)
-- fire "Sell All", then fly back. Only runs when the backpack actually holds ore.
loopify(function()
if not S.autoSell then return end
if not (S._mySellPad and S._flyTo and S._hrpOf) then return end
local ore = LP:GetAttribute("FS_BackpackOre") or 0
if ore <= 0 then return end
local anchor, prompt = S._mySellPad()
if not anchor then return end
local hrp = S._hrpOf(); if not hrp then return end
local home = hrp.Position
local dist = (anchor.Position - hrp.Position).Magnitude
if dist > 12 then
if not S._flyTo(anchor.Position + Vector3.new(0, 3, 0), 8) then return end
end
if prompt and fireproximityprompt then
for _ = 1, 3 do
pcall(fireproximityprompt, prompt)
task.wait(0.35)
if (LP:GetAttribute("FS_BackpackOre") or 0) <= 0 then break end
end
end
stats.sells = (stats.sells or 0) + 1
if S.returnHome ~= false and dist > 12 then S._flyTo(home, 6) end
end, 6, "Auto sell")
-- ======================================================= movement ========
-- Both shard pickup and selling are validated SERVER-SIDE by proximity, so they genuinely
-- require being there. We glide in steps (~160 studs/s, close to the game's own jetpack) so it
-- reads as normal flying rather than a snap teleport, and we return to where we started.
hrpOf = function() local ch=LP.Character; return ch and ch:FindFirstChild("HumanoidRootPart") end
S._hrpOf = hrpOf
-- Travel at the character's REAL jetpack speed. Moving faster than FS_JetpackFlightSpeed trips
-- the server's movement correction (FS_MovementCorrectionToken climbs and you get yanked back),
-- which is exactly why the first version never arrived. At legit speed it is just normal flight.
flyTo = function(pos, arrive, timeout)
local hrp=hrpOf(); if not hrp then return false end
arrive = arrive or 6
local speed = (LP:GetAttribute("FS_JetpackFlightSpeed") or 80) * 0.9
local dt = 0.06
local perStep = math.max(2, speed * dt)
local t0 = os.clock()
timeout = timeout or math.clamp((pos - hrp.Position).Magnitude / math.max(speed, 1) + 6, 8, 30)
while live() and os.clock()-t0 < timeout do
local h = hrpOf(); if not h then return false end
local cur = h.Position
local d = pos - cur
if d.Magnitude <= arrive then return true end
local ok = pcall(function() h.CFrame = CFrame.new(cur + d.Unit * math.min(d.Magnitude, perStep)) end)
if not ok then return false end
task.wait(dt)
end
local h = hrpOf()
return (h ~= nil) and (h.Position - pos).Magnitude <= arrive + 4
end
S._flyTo = flyTo
-- our own event drops only. Other players' drops live in sibling folders and are not ours to take.
-- Two kinds of drops live under FarmStar.EventDrops:
-- Shared/ -> the actual EVENT SHARDS, FS_DropOwner == 0, free for anyone to fly over
-- <userId>/ -> private drops (consumables/batteries) owned by that player
-- We take the shared shards plus our OWN private drops, never another player's.
myEventDrops = function()
local out={}
local fs=workspace:FindFirstChild("FarmStar"); if not fs then return out end
local eds=fs:FindFirstChild("EventDrops"); if not eds then return out end
local now=os.time()
local hrp=hrpOf()
local here=hrp and hrp.Position or Vector3.new()
local function scan(folder)
if not folder then return end
for _,d in ipairs(folder:GetDescendants()) do
if d:IsA("BasePart") and d.Name=="FS_EventDrop" then
local exp=d:GetAttribute("FS_DropExpireAt")
local owner=d:GetAttribute("FS_DropOwner")
if (owner==0 or owner==LP.UserId) and (type(exp)~="number" or exp>now) then
out[#out+1]=d
end
end
end
end
scan(eds:FindFirstChild("Shared"))
scan(eds:FindFirstChild(tostring(LP.UserId)))
-- shards first, then nearest first, so the valuable pickups are never missed on a short event
table.sort(out, function(a,b)
local sa = (a:GetAttribute("FS_DropKind")=="shard") and 1 or 0
local sb = (b:GetAttribute("FS_DropKind")=="shard") and 1 or 0
if sa ~= sb then return sa > sb end
return (a.Position-here).Magnitude < (b.Position-here).Magnitude
end)
return out
end
S._myDrops=myEventDrops
-- our own sell pad (each plot has one under Platforms.<userId>.Shops)
mySellPad = function()
local fs=workspace:FindFirstChild("FarmStar"); if not fs then return nil end
local plats=fs:FindFirstChild("Platforms"); if not plats then return nil end
local mine=plats:FindFirstChild(tostring(LP.UserId)); if not mine then return nil end
local anchor=mine:FindFirstChild("FS_SellPromptAnchor", true)
if not anchor then return nil end
local prompt=anchor:FindFirstChildWhichIsA("ProximityPrompt")
return anchor, prompt
end
S._mySellPad=mySellPad
-- ======================================================= drones ==========
-- Rarity ladder + catalog come straight from the game's own config, so the target
-- list we hand to SetAutoRollTargets is exactly what its own panel would send.
local DroneCatalog, RarityConfig
pcall(function()
local Cfg = RS:WaitForChild("Config")
DroneCatalog = require(Cfg:WaitForChild("DroneCatalog"))
RarityConfig = require(Cfg:WaitForChild("RarityConfig"))
end)
local RARITY_ORDER = (RarityConfig and RarityConfig.order) or
{ "Common","Uncommon","Rare","Epic","Legendary","Mythic","Secret","Divine","Exotic","Prismatic","Transcendent","Void" }
local function rankOf(rarity)
if RarityConfig and RarityConfig.rank then local ok,v = pcall(RarityConfig.rank, rarity); if ok and type(v)=="number" then return v end end
for i,r in ipairs(RARITY_ORDER) do if r == rarity then return i end end
return 0
end
local function rarityOfDrone(key)
if DroneCatalog and DroneCatalog.rarity then local ok,v = pcall(DroneCatalog.rarity, key); if ok then return v end end
return nil
end
local function targetsForSelection()
local out, seen = {}, {}
if not (DroneCatalog and DroneCatalog.obtainableDronesOfRarity) then return out end
for _, r in ipairs(RARITY_ORDER) do
if S.rarities and S.rarities[r] then
local ok, list = pcall(DroneCatalog.obtainableDronesOfRarity, r)
if ok and type(list) == "table" then
for _, k in ipairs(list) do if type(k)=="string" and not seen[k] then seen[k]=true; out[#out+1]=k end end
end
end
end
return out
end
local function pushRollTargets()
local t = targetsForSelection()
pcall(function() local r=R("SetAutoRollTargets"); if r then r:FireServer({ targets = t }) end end)
return #t
end
local function setRollActive(v)
pcall(function() local r=R("SetAutoRollActive"); if r then r:FireServer({ active = v and true or false }) end end)
end
-- drone inventory mirror (InventorySync items: {uid, kind, droneType, location, level, favorite})
local invItems = {}
S._inv = invItems
do
local r = R("InventorySync")
if r then track(r.OnClientEvent:Connect(function(p)
local src = p
if type(src) == "table" and src.items == nil then
for _, v in pairs(src) do if type(v)=="table" and v.items then src = v break end end
end
local items = type(src)=="table" and src.items or nil
if type(items) ~= "table" then return end
table.clear(invItems)
for _, it in pairs(items) do if type(it)=="table" and it.kind=="drone" then invItems[#invItems+1]=it end end
end)) end
end
-- returns: placedCount, storedCount, list of upgrade suggestions {dock, from, to, gain}
local function droneAnalysis()
local placed, stored = {}, {}
for _, it in ipairs(invItems) do
local loc = tostring(it.location or "")
local d = { uid=it.uid, key=it.droneType, fav=it.favorite,
rank=rankOf(rarityOfDrone(it.droneType)), rarity=rarityOfDrone(it.droneType) }
local dock = loc:match("^dock:(%d+)")
if dock then d.dock = tonumber(dock); placed[#placed+1]=d else stored[#stored+1]=d end
end
table.sort(placed, function(a,b) return a.rank < b.rank end) -- weakest first
table.sort(stored, function(a,b) return a.rank > b.rank end) -- strongest first
local sugg, si = {}, 1
for _, weak in ipairs(placed) do
local best = stored[si]
if best and best.rank > weak.rank and not weak.fav then
sugg[#sugg+1] = { dock=weak.dock, from=weak.key, fromR=weak.rarity, to=best.key, toR=best.rarity }
si = si + 1
end
end
return placed, stored, sugg
end
S._droneAnalysis = droneAnalysis
-- ======================================================= loading screen ===
local bootDone = false
do
local bg = mk("ScreenGui",{Name="OrbitalBoot",ResetOnSpawn=false,IgnoreGuiInset=true,DisplayOrder=1000,Parent=HOST})
local card = mk("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.new(0.5,0,0.5,0),Size=UDim2.new(0,380,0,140),
BackgroundColor3=C.surf,BackgroundTransparency=1,Parent=bg},{corner(16),stroke(0.55)})
mk("UIGradient",{Rotation=90,Color=ColorSequence.new(Color3.fromRGB(255,255,255),Color3.fromRGB(170,170,170)),Parent=card})
local dot = mk("Frame",{Position=UDim2.new(0,26,0,28),Size=UDim2.new(0,20,0,20),BackgroundColor3=C.acc,
BackgroundTransparency=1,Parent=card},{corner(6)})
local t1 = mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,58,0,26),Size=UDim2.new(1,-80,0,22),Text="ORBITAL",
TextColor3=C.txt,TextTransparency=1,TextXAlignment=Enum.TextXAlignment.Left,Font=FB,TextSize=22,Parent=card})
local t2 = mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,58,0,50),Size=UDim2.new(1,-80,0,16),Text="mine a planet",
TextColor3=C.sub,TextTransparency=1,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=12,Parent=card})
local step = mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,26,1,-46),Size=UDim2.new(1,-52,0,14),Text="",
TextColor3=C.sub,TextTransparency=1,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=card})
local barBg = mk("Frame",{Position=UDim2.new(0,26,1,-28),Size=UDim2.new(1,-52,0,5),BackgroundColor3=C.surf2,
BackgroundTransparency=1,BorderSizePixel=0,Parent=card},{corner(3)})
local bar = mk("Frame",{Size=UDim2.new(0,0,1,0),BackgroundColor3=C.acc,BorderSizePixel=0,Parent=barBg},{corner(3)})
tw(card,{BackgroundTransparency=0.02},0.3) tw(dot,{BackgroundTransparency=0},0.3)
tw(t1,{TextTransparency=0},0.35) tw(t2,{TextTransparency=0},0.4)
tw(step,{TextTransparency=0},0.4) tw(barBg,{BackgroundTransparency=0},0.4)
task.spawn(function()
local steps={"reading plot","indexing docks","binding remotes","syncing state","ready"}
for i,s in ipairs(steps) do
if step.Parent then step.Text=s end
tw(bar,{Size=UDim2.new(i/#steps,0,1,0)},0.26)
task.wait(0.26)
end
task.wait(0.2)
tw(card,{BackgroundTransparency=1},0.3) tw(t1,{TextTransparency=1},0.28) tw(t2,{TextTransparency=1},0.28)
tw(step,{TextTransparency=1},0.28) tw(dot,{BackgroundTransparency=1},0.28) tw(barBg,{BackgroundTransparency=1},0.28)
task.wait(0.34)
pcall(function() bg:Destroy() end)
bootDone = true
gui.Enabled = true -- window only appears AFTER the loader
end)
end
-- ======================================================= window ===========
local W,H = 560, 400
local win = mk("Frame",{Name="Win",AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.new(0.5,0,0.5,0),
Size=UDim2.new(0,W,0,H),BackgroundColor3=C.bg,Active=true,Draggable=true,Parent=gui},{corner(16),stroke(0.5)})
mk("UIGradient",{Rotation=90,Color=ColorSequence.new(Color3.fromRGB(255,255,255),Color3.fromRGB(184,184,184)),Parent=win})
local bar = mk("Frame",{Size=UDim2.new(1,0,0,56),BackgroundTransparency=1,Parent=win})
mk("Frame",{Position=UDim2.new(0,20,0.5,-10),Size=UDim2.new(0,20,0,20),BackgroundColor3=C.acc,Parent=bar},{corner(6)})
mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,52,0,12),Size=UDim2.new(1,-150,0,19),Text="ORBITAL",
TextColor3=C.txt,TextXAlignment=Enum.TextXAlignment.Left,Font=FB,TextSize=18,Parent=bar})
mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,52,0,33),Size=UDim2.new(1,-150,0,14),Text="mine a planet",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=bar})
local cashLbl = mk("TextLabel",{AnchorPoint=Vector2.new(1,0.5),Position=UDim2.new(1,-58,0.5,0),Size=UDim2.new(0,150,0,18),
Text="",TextColor3=C.good,TextXAlignment=Enum.TextXAlignment.Right,Font=FM,TextSize=13,BackgroundTransparency=1,Parent=bar})
local hideB = mk("TextButton",{AnchorPoint=Vector2.new(1,0.5),Position=UDim2.new(1,-18,0.5,0),Size=UDim2.new(0,28,0,28),
BackgroundColor3=C.surf2,Text="-",TextColor3=C.txt,Font=FB,TextSize=16,AutoButtonColor=false,Parent=bar},{corner(8)})
mk("Frame",{Position=UDim2.new(0,20,0,56),Size=UDim2.new(1,-40,0,1),BackgroundColor3=C.line,
BackgroundTransparency=0.6,BorderSizePixel=0,Parent=win})
local side = mk("Frame",{Position=UDim2.new(0,16,0,68),Size=UDim2.new(0,136,1,-84),BackgroundColor3=C.surf,Parent=win},
{corner(12),mk("UIListLayout",{Padding=UDim.new(0,5),SortOrder=Enum.SortOrder.LayoutOrder}),pad(8)})
local content = mk("Frame",{Position=UDim2.new(0,166,0,68),Size=UDim2.new(1,-182,1,-84),BackgroundTransparency=1,ClipsDescendants=true,Parent=win})
local pages,tabs = {},{}
local function selectTab(id)
for k,pg in pairs(pages) do pg.Visible=(k==id) end
for k,b in pairs(tabs) do
tw(b,{BackgroundTransparency=(k==id) and 0 or 1},0.15)
local l=b:FindFirstChildOfClass("TextLabel"); if l then l.TextColor3=(k==id) and C.txt or C.sub end
end
end
local tOrd=0
local function addTab(id,label)
tOrd=tOrd+1
local b=mk("TextButton",{Size=UDim2.new(1,0,0,34),BackgroundColor3=C.surf2,BackgroundTransparency=1,Text="",
AutoButtonColor=false,LayoutOrder=tOrd,Parent=side},{corner(9)})
mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,12,0,0),Size=UDim2.new(1,-16,1,0),Text=label,
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=b})
local pg=mk("ScrollingFrame",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,BorderSizePixel=0,Visible=false,
CanvasSize=UDim2.new(),AutomaticCanvasSize=Enum.AutomaticSize.Y,ScrollBarThickness=3,ScrollBarImageColor3=C.acc,Parent=content},
{mk("UIListLayout",{Padding=UDim.new(0,9),SortOrder=Enum.SortOrder.LayoutOrder})})
pages[id]=pg tabs[id]=b
track(b.MouseButton1Click:Connect(function() selectTab(id) end))
return pg
end
local ord=0
local function O() ord=ord+1 return ord end
local function sect(p,t) mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,14),Text=string.upper(t),
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FB,TextSize=10,LayoutOrder=O(),Parent=p}) end
local function Toggle(p,label,key,cb)
local row=mk("Frame",{Size=UDim2.new(1,0,0,42),BackgroundColor3=C.surf,LayoutOrder=O(),Parent=p},{corner(10),stroke(0.85)})
mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,14,0,0),Size=UDim2.new(1,-70,1,0),Text=label,
TextColor3=C.txt,TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=row})
local knob=mk("Frame",{AnchorPoint=Vector2.new(1,0.5),Position=UDim2.new(1,-12,0.5,0),Size=UDim2.new(0,42,0,22),
BackgroundColor3=S[key] and C.acc or C.surf2,Parent=row},{corner(11)})
local dot=mk("Frame",{AnchorPoint=Vector2.new(0,0.5),Position=UDim2.new(0,S[key] and 22 or 2,0.5,0),Size=UDim2.new(0,18,0,18),
BackgroundColor3=C.txt,Parent=knob},{corner(9)})
local btn=mk("TextButton",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Text="",Parent=row})
track(btn.MouseButton1Click:Connect(function()
S[key]=not S[key]
tw(knob,{BackgroundColor3=S[key] and C.acc or C.surf2},0.15)
tw(dot,{Position=UDim2.new(0,S[key] and 22 or 2,0.5,0)},0.15)
if cb then pcall(cb,S[key]) end
end))
end
local function card(p,h) return mk("Frame",{Size=UDim2.new(1,0,0,h),BackgroundColor3=C.surf,LayoutOrder=O(),Parent=p},{corner(10),stroke(0.85),pad(13)}) end
local U={}
do local p=addTab("auto","Automation")
sect(p,"Ore")
Toggle(p,"Auto collect","autoCollect",function(v) setPerk("autoCollect",v) end)
Toggle(p,"Auto sell","autoSell",function(v) setPerk("autoSell",v) end)
sect(p,"Status")
local c=card(p,58)
U.s1=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,17),Text="",TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=c})
U.s2=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,20),Size=UDim2.new(1,0,0,16),Text="",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=c})
end
do local p=addTab("upg","Upgrades")
sect(p,"Auto")
Toggle(p,"Auto upgrade all","autoUpgrade")
sect(p,"Tracks")
U.upRows={}
for _,u in ipairs(UP) do
local c=card(p,38)
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(0.5,0,1,0),Text=u.label,TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=12,Parent=c})
U.upRows[u.k]=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0.5,0,0,0),Size=UDim2.new(0.5,0,1,0),Text="-",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Right,Font=FR,TextSize=11,Parent=c})
end
end
do local p=addTab("drn","Drones")
sect(p,"Auto roll")
Toggle(p,"Auto roll drones","autoRoll",function(v)
local n=pushRollTargets(); setRollActive(v)
if v then notify("Auto roll on", n.." drone types targeted","good") end
end)
sect(p,"Target rarities")
local grid=mk("Frame",{Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,BackgroundTransparency=1,LayoutOrder=O(),Parent=p},
{mk("UIGridLayout",{CellSize=UDim2.new(0.5,-4,0,30),CellPadding=UDim2.new(0,8,0,8),SortOrder=Enum.SortOrder.LayoutOrder})})
U.rarChips={}
for _,r in ipairs(RARITY_ORDER) do
local on=(S.rarities and S.rarities[r]) and true or false
local chip=mk("TextButton",{BackgroundColor3=on and C.acc or C.surf,Text="",AutoButtonColor=false,Parent=grid},{corner(8),stroke(0.85)})
local lb=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Text=r,
TextColor3=on and Color3.fromRGB(12,16,26) or C.sub,Font=FM,TextSize=11,Parent=chip})
U.rarChips[r]={chip=chip,lb=lb}
track(chip.MouseButton1Click:Connect(function()
S.rarities=S.rarities or {}
S.rarities[r]=not S.rarities[r]
local o=S.rarities[r] and true or false
tw(chip,{BackgroundColor3=o and C.acc or C.surf},0.14)
lb.TextColor3 = o and Color3.fromRGB(12,16,26) or C.sub
local n=pushRollTargets()
if U.rollInfo then U.rollInfo.Text=n.." drone types targeted" end
end))
end
U.rollInfo=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,16),Text="",TextColor3=C.sub,
TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,LayoutOrder=O(),Parent=p})
sect(p,"Loadout")
local dc=card(p,58)
U.d1=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,17),Text="",TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=dc})
U.d2=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,20),Size=UDim2.new(1,0,0,16),Text="",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=dc})
sect(p,"Suggested swaps")
U.swapBox=mk("Frame",{Size=UDim2.new(1,0,0,116),BackgroundColor3=C.surf,LayoutOrder=O(),Parent=p},
{corner(10),stroke(0.85),pad(11),mk("UIListLayout",{Padding=UDim.new(0,4),SortOrder=Enum.SortOrder.LayoutOrder})})
U.swapEmpty=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,15),Text="Loadout is optimal",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=U.swapBox})
end
do local p=addTab("evt","Events")
sect(p,"Shard farming")
Toggle(p,"Auto collect shards","autoEvent")
Toggle(p,"Return to start after","returnHome")
sect(p,"Progress")
local c1=card(p,44)
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(0.45,0,1,0),Text="UFO",TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=c1})
U.ufo=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0.45,0,0,0),Size=UDim2.new(0.55,0,1,0),Text="-",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Right,Font=FR,TextSize=12,Parent=c1})
local c2=card(p,44)
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(0.45,0,1,0),Text="JellyFish",TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=c2})
U.jelly=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0.45,0,0,0),Size=UDim2.new(0.55,0,1,0),Text="-",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Right,Font=FR,TextSize=12,Parent=c2})
sect(p,"Live")
local c3=card(p,58)
U.e1=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,17),Text="",TextColor3=C.txt,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=c3})
U.e2=mk("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,20),Size=UDim2.new(1,0,0,16),Text="",
TextColor3=C.sub,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=c3})
end
do local p=addTab("diag","Diagnostics")
sect(p,"Health")
local c=card(p,40)
U.health=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Text="Nominal",TextColor3=C.good,
TextXAlignment=Enum.TextXAlignment.Left,Font=FM,TextSize=13,Parent=c})
sect(p,"Errors")
U.errBox=mk("Frame",{Size=UDim2.new(1,0,0,120),BackgroundColor3=C.surf,LayoutOrder=O(),Parent=p},
{corner(10),stroke(0.85),pad(11),mk("UIListLayout",{Padding=UDim.new(0,4),SortOrder=Enum.SortOrder.LayoutOrder})})
U.errEmpty=mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,15),Text="None",TextColor3=C.sub,
TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=11,Parent=U.errBox})
Toggle(p,"Notifications","notify")
end
selectTab("auto")
-- ======================================================= loops ============
loopify(function()
if not S.autoCollect then return end
local n=0
for part,pr in pairs(myDocks) do
if not live() then break end
local ok,ore=pcall(function() return part.Parent and (part:GetAttribute("FS_OreCount") or 0) or nil end)
if not ok or ore==nil then myDocks[part]=nil
elseif ore>0 and pr.Parent then pcall(fireproximityprompt,pr) n=n+1 task.wait(0.03) end
end
if n>0 then stats.collected=stats.collected+n end
end, function() return (S.collectMs or 140)/1000 end, "Auto collect")
loopify(function() reindexDocks() end, 12, "Dock reindex")
loopify(function() pullState() end, 6, "State sync")
-- auto upgrade: buy any track that is not maxed and is affordable
loopify(function()
if not S.autoUpgrade then return end
for _,u in ipairs(UP) do
if not live() then break end
local st=upState[u.k]
if type(st)=="table" and type(st.nextCost)=="number" and cash>=st.nextCost then
local r=R(u.req)
if r then
pcall(function() r:FireServer({}) end)
stats.upgrades=stats.upgrades+1
task.wait(0.4)
end
end
end
end, 3, "Auto upgrade")
loopify(function()
local ore,docks=myOre()
if U.s1 then U.s1.Text=string.format("Docks %d Ore %d", docks, ore) end
if U.s2 then U.s2.Text=string.format("Collected %d Upgrades %d", stats.collected, stats.upgrades) end
if cashLbl then
local v=cash
local s = v>=1e12 and string.format("%.2fT",v/1e12) or v>=1e9 and string.format("%.2fB",v/1e9)
or v>=1e6 and string.format("%.2fM",v/1e6) or v>=1e3 and string.format("%.1fk",v/1e3) or string.format("%d",v)
cashLbl.Text=s
end
for _,u in ipairs(UP) do
local lb=U.upRows and U.upRows[u.k]
if lb then
local st=upState[u.k]
if type(st)~="table" then lb.Text="-" lb.TextColor3=C.sub
elseif st.nextCost==nil then lb.Text="MAX" lb.TextColor3=C.good
else
local c=st.nextCost
local s = c>=1e12 and string.format("%.2fT",c/1e12) or c>=1e9 and string.format("%.2fB",c/1e9)
or c>=1e6 and string.format("%.2fM",c/1e6) or c>=1e3 and string.format("%.1fk",c/1e3) or tostring(c)
lb.Text=(st.level and ("L"..tostring(st.level).." ") or "")..s
lb.TextColor3=(cash>=c) and C.acc or C.sub
end
end
end
do
local u,j = shards("UFO"), shards("JellyFish")
if U.ufo then U.ufo.Text=string.format("%d/10 shards %d token%s", u%10, math.floor(u/10), (math.floor(u/10)==1) and "" or "s")
U.ufo.TextColor3=(u>0) and C.acc or C.sub end
if U.jelly then U.jelly.Text=string.format("%d/10 shards %d token%s", j%10, math.floor(j/10), (math.floor(j/10)==1) and "" or "s")
U.jelly.TextColor3=(j>0) and C.acc or C.sub end
local pend = ev.pending or 0
if U.e1 then U.e1.Text = (pend > 0) and (pend .. " drop" .. ((pend == 1) and "" or "s") .. " waiting") or "No drops right now" end
if U.e2 then U.e2.Text = string.format("Picked up %d Trips %d Backpack %s",
ev.claimed or 0, ev.moves or 0, tostring(LP:GetAttribute("FS_BackpackOre") or 0)) end
end
do
local placed, stored, sugg = droneAnalysis()
if U.d1 then U.d1.Text=string.format("Placed %d Stored %d", #placed, #stored) end
if U.d2 then
local bestP = placed[#placed]; local bestS = stored[1]
U.d2.Text = string.format("Best placed %s Best stored %s",
(bestP and (bestP.rarity or "?")) or "-", (bestS and (bestS.rarity or "?")) or "-")
end
if U.swapBox then
for _,ch in ipairs(U.swapBox:GetChildren()) do if ch:IsA("TextLabel") and ch~=U.swapEmpty then ch:Destroy() end end
U.swapEmpty.Visible=(#sugg==0)
for i=1,math.min(#sugg,5) do local s=sugg[i]
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,15),
Text=string.format("Dock %s %s -> %s", tostring(s.dock), tostring(s.fromR or s.from), tostring(s.toR or s.to)),
TextColor3=C.acc,TextTruncate=Enum.TextTruncate.AtEnd,TextXAlignment=Enum.TextXAlignment.Left,
Font=FR,TextSize=10,LayoutOrder=i,Parent=U.swapBox})
end
end
end
if U.health then
U.health.Text=(stats.errors==0) and "Nominal" or (stats.errors.." error(s)")
U.health.TextColor3=(stats.errors==0) and C.good or C.bad
end
if U.errBox then
for _,ch in ipairs(U.errBox:GetChildren()) do if ch:IsA("TextLabel") and ch~=U.errEmpty then ch:Destroy() end end
U.errEmpty.Visible=(#errLog==0)
for i=1,math.min(#errLog,5) do local e=errLog[i]
mk("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,0,15),Text=e.t.." "..e.f..": "..e.e,TextColor3=C.bad,
TextTruncate=Enum.TextTruncate.AtEnd,TextXAlignment=Enum.TextXAlignment.Left,Font=FR,TextSize=10,LayoutOrder=i,Parent=U.errBox})
end
end
end, 1, "UI")
-- chrome
local shown=true
track(hideB.MouseButton1Click:Connect(function()
shown=not shown
tw(win,{Size=shown and UDim2.new(0,W,0,H) or UDim2.new(0,W,0,56)},0.22)
side.Visible=shown content.Visible=shown
end))
track(UserInputService.InputBegan:Connect(function(i,gp)
if gp then return end
if i.KeyCode==Enum.KeyCode.RightControl and bootDone then gui.Enabled=not gui.Enabled end
end))
S._cleanup=function() S.run=false for _,c in ipairs(conns) do pcall(function() c:Disconnect() end) end pcall(function() gui:Destroy() end) end
task.delay(2.2,function() if live() then notify("Ready","Wave 2 online.","good") end end)
end)
if not BOOTOK then warn("[ORBITAL] "..tostring(BOOTERR)) end
Description
Ore Auto collect — pulls ore from your docks across all floors. Only fires on docks that actually hold ore, and only ever touches your own plot. Auto sell — flies to your sell pad, sells, then returns to where you were. Separate toggle, so you can collect without selling. Upgrades Auto upgrade buys any track that isn't maxed once you can afford it. Luck and Planet work now; the per-floor tracks (laser, cargo, dock storage) are still being mapped. All six show live cost and MAX status. Events Collects UFO and Jellyfish shards during incidents by flying over the drops, prioritising shards over item drops and taking the nearest first. Returns to your starting spot afterwards, and skips other players' drops. Shows shard progress and token count for both events. Drones Auto roll with a rarity picker across all twelve tiers, so you can target only what you care about. Loadout analyser compares your placed drones against storage and lists which docks could be upgraded. It reports suggestions only — it won't move drones for you yet, since the swap call isn't verified and I'd rather not risk your inventory. Diagnostics Every feature runs guarded. If one fails it's listed with the reason and line number, and you get a single notification rather than repeated spam.
Commentaires (0)
Connectez-vous pour participer à la conversation
- Soyez le premier à commenter.
Questions fréquentes
- Comment utiliser le script ORBITAL — Mine a Planet ?
- Copiez le code ci-dessus, ouvrez votre exécuteur Roblox, collez le code et appuyez sur exécuter pendant que vous êtes dans le jeu. Les fonctionnalités s'activent instantanément une fois le script lancé.
- Le script ORBITAL — Mine a Planet est-il gratuit ?
- Oui. Ce script est gratuit à copier et utiliser. S'il utilise un système de clé, suivez le lien « Obtenir la clé » pour le débloquer gratuitement.
- Le script ORBITAL — Mine a Planet est-il sûr à utiliser ?
- Le code source complet est affiché sur cette page pour que vous puissiez lire exactement ce qu'il fait avant de l'exécuter. Utilisez toujours un exécuteur de confiance, et n'oubliez pas que l'utilisation de scripts est contraire aux conditions d'utilisation de Roblox — utilisez-les à vos propres risques.
- Quel exécuteur fonctionne avec ORBITAL — Mine a Planet ?
- Ce script fonctionne avec la plupart des exécuteurs Roblox populaires. Consultez notre page d'exécuteurs pour trouver un exécuteur gratuit ou payant fiable pour votre appareil.