local environment = (getgenv and getgenv()) or _G if environment.__BUCKET_HUB_RUNNING then warn("[Bucket Hub] Already running; skipped duplicate load.") return end environment.__BUCKET_HUB_RUNNING = true local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local CollectionService = game:GetService("CollectionService") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local Workspace = game:GetService("Workspace") local Lighting = game:GetService("Lighting") local LocalPlayer = Players.LocalPlayer -- ========================================================= -- Remote helpers (mirrors Verdant.Remotes on the client) -- ========================================================= local RemotesFolder = ReplicatedStorage:WaitForChild("VerdantRemotes") local remoteCache: { [string]: Instance } = {} local function getRemote(name: string): Instance? if remoteCache[name] then return remoteCache[name] end local inst = RemotesFolder:WaitForChild("VDT_" .. name, 5) if inst then remoteCache[name] = inst end return inst end local function fire(name: string, ...: any) local r = getRemote(name) if r and r:IsA("RemoteEvent") then r:FireServer(...) end end local function invoke(name: string, ...: any): any local r = getRemote(name) if r and r:IsA("RemoteFunction") then local ok, result = pcall(r.InvokeServer, r, ...) if ok then return result end end return nil end -- ========================================================= -- Game helpers -- ========================================================= local function getCharacter(): Model? return LocalPlayer.Character end local function getHumanoid(): Humanoid? local char = getCharacter() return char and char:FindFirstChildOfClass("Humanoid") or nil end local function getRoot(): BasePart? local char = getCharacter() return char and char:FindFirstChild("HumanoidRootPart") :: BasePart? or nil end local function getBucketFill(): number return tonumber(LocalPlayer:GetAttribute("BucketFill")) or 0 end local function getBucketTool(): Tool? local char = getCharacter() if char then local equipped = char:FindFirstChild("Bucket") if equipped and equipped:IsA("Tool") then return equipped end end local backpack = LocalPlayer:FindFirstChildOfClass("Backpack") if backpack then local tool = backpack:FindFirstChild("Bucket") if tool and tool:IsA("Tool") then return tool end end return nil end local function isBucketEquipped(): boolean local char = getCharacter() return char ~= nil and char:FindFirstChild("Bucket") ~= nil end local function ensureBucketEquipped(): boolean if isBucketEquipped() then return true end local humanoid = getHumanoid() local tool = getBucketTool() if humanoid and tool then humanoid:EquipTool(tool) return true end return false end local function instancePosition(inst: Instance): Vector3? if inst:IsA("BasePart") then return inst.Position elseif inst:IsA("Model") then local ok, cf = pcall(function() return inst:GetPivot() end) if ok then return cf.Position end local part = inst:FindFirstChildWhichIsA("BasePart", true) return part and part.Position or nil elseif inst:IsA("ProximityPrompt") then local parent = inst.Parent if parent and parent:IsA("BasePart") then return parent.Position elseif parent then local pp = parent:FindFirstChildWhichIsA("BasePart", true) return pp and pp.Position or nil end end return nil end -- Finds the ProximityPrompt belonging to a "Pour"-tagged part/model. local function promptFor(inst: Instance): ProximityPrompt? if inst:IsA("ProximityPrompt") then return inst end local direct = inst:FindFirstChildWhichIsA("ProximityPrompt") if direct then return direct end local container: Instance? = inst:IsA("Model") and inst or inst.Parent if container then return container:FindFirstChildWhichIsA("ProximityPrompt", true) end return nil end -- ========================================================= -- SwimController hook (THE real Infinite Oxygen fix) -- ========================================================= -- The game's drowning is 100% client-side, driven by the SwimController -- module in PlayerScripts.Controllers. Requiring a ModuleScript returns the -- SAME cached table the game uses, so we can pin its internal state. local swimController: any = nil local function findSwimController(): any if swimController then return swimController end local ok, result = pcall(function() local ps = LocalPlayer:FindFirstChildOfClass("PlayerScripts") local folder = ps and ps:FindFirstChild("Controllers") if not folder then return nil end -- try the expected name first local named = folder:FindFirstChild("SwimController") if named and named:IsA("ModuleScript") then local t = require(named) :: any if type(t) == "table" and t._startDrown then return t end end -- fallback: scan every controller for the drowning API for _, child in folder:GetChildren() do if child:IsA("ModuleScript") then local okReq, t = pcall(require, child) if okReq and type(t) == "table" and t._startDrown and t._swimStep then return t end end end return nil end) if ok and result then swimController = result end return swimController end -- Cancels an in-progress drown and restores walkspeed / animation. local function cancelDrown(sc: any) if not sc._drowning then return end sc._drowning = false sc._drownElapsed = 0 if sc._drownTrack and sc._drownTrack.IsPlaying then pcall(function() sc._drownTrack:Stop(0.2) end) end if sc._swimTrack and sc._swimming and not sc._swimTrack.IsPlaying then pcall(function() sc._swimTrack:Play(0.2) end) end if sc._humanoid and sc._savedWalkSpeed ~= nil then sc._humanoid.WalkSpeed = sc._savedWalkSpeed sc._savedWalkSpeed = nil end LocalPlayer:SetAttribute("Drowning", nil) end -- Legacy fallback: pins any numeric Oxygen/Air/Breath attribute (kept in -- case the game ever adds one; harmless otherwise). local oxygenBaselines: { [string]: number } = {} local function pinOxygenAttributes(container: Instance) for name, value in container:GetAttributes() do if type(value) == "number" and (string.find(name, "Oxygen") or string.find(name, "Air") or string.find(name, "Breath")) then local baseline = oxygenBaselines[name] if baseline == nil or value > baseline then oxygenBaselines[name] = value elseif value < baseline then pcall(function() container:SetAttribute(name, baseline) end) end end end end -- ========================================================= -- Anti-Death + Hide Players helpers (moved ABOVE the loops -- that call them — this was the line 518 nil error) -- ========================================================= local function applyAntiDeath(humanoid: Humanoid, on: boolean) pcall(function() humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, not on) if on then humanoid.BreakJointsOnDeath = false end end) end local function setCharacterHidden(char: Model, hidden: boolean) for _, d in char:GetDescendants() do if d:IsA("BasePart") then d.LocalTransparencyModifier = hidden and 1 or 0 elseif d:IsA("Decal") then d.LocalTransparencyModifier = hidden and 1 or 0 end end end -- ========================================================= -- Nearest-target queries -- ========================================================= local function nearestTaggedPos(tag: string): (Instance?, Vector3?, number) local root = getRoot() if not root then return nil, nil, math.huge end local best: Instance? = nil local bestPos: Vector3? = nil local bestDist = math.huge for _, inst in CollectionService:GetTagged(tag) do local pos = instancePosition(inst) if pos then local d = (pos - root.Position).Magnitude if d < bestDist then bestDist = d best = inst bestPos = pos end end end return best, bestPos, bestDist end local function nearestPour(): (ProximityPrompt?, Vector3?, number) local root = getRoot() if not root then return nil, nil, math.huge end local bestPrompt: ProximityPrompt? = nil local bestPos: Vector3? = nil local bestDist = math.huge for _, inst in CollectionService:GetTagged("Pour") do local prompt = promptFor(inst) local pos = instancePosition(inst) if prompt and pos then local d = (pos - root.Position).Magnitude if d < bestDist then bestDist = d bestPrompt = prompt bestPos = pos end end end return bestPrompt, bestPos, bestDist end local function nearestChest(): (Instance?, Vector3?, number) local root = getRoot() if not root then return nil, nil, math.huge end local best: Instance? = nil local bestPos: Vector3? = nil local bestDist = math.huge for _, inst in CollectionService:GetTagged("Chest") do local prompt = promptFor(inst) local pos = instancePosition(inst) local openable = (prompt == nil) or prompt.Enabled if pos and openable then local d = (pos - root.Position).Magnitude if d < bestDist then bestDist = d best = inst bestPos = pos end end end return best, bestPos, bestDist end -- ========================================================= -- Movement / teleport helpers -- ========================================================= local function teleportTo(pos: Vector3) local root = getRoot() if root then root.AssemblyLinearVelocity = Vector3.zero root.CFrame = CFrame.new(pos) end end local function moveNear(pos: Vector3, dist: number): boolean local root = getRoot() if not root then return false end local flat = Vector3.new(root.Position.X - pos.X, 0, root.Position.Z - pos.Z) if flat.Magnitude < 0.1 then flat = Vector3.new(0, 0, 1) end local dest = pos + flat.Unit * dist + Vector3.new(0, 3, 0) root.AssemblyLinearVelocity = Vector3.zero root.CFrame = CFrame.new(dest, pos) return true end -- ========================================================= -- Feature state -- ========================================================= local State = { -- actions autoScoop = false, scoopInterval = 0.2, autoPour = false, autoTokens = false, autoChests = false, autoTp = true, returnAfter = false, proximity = 8, -- player speedEnabled = false, walkSpeed = 32, jumpEnabled = false, jumpPower = 75, infiniteJump = false, noclip = false, fly = false, flySpeed = 60, swimSpeedEnabled = false, swimSpeed = 40, gravityEnabled = false, gravity = 196.2, -- survival antiDeath = false, infOxygen = false, -- hooks SwimController: full meter + no drowning freeze = false, -- visuals espChests = false, espDrains = false, espWater = false, espPlayers = false, hidePlayers = false, fovEnabled = false, fov = 70, -- server / misc antiAfk = false, fullbright = false, -- settings toggleKey = Enum.KeyCode.LeftAlt, unlockMouse = true, -- force-free the cursor while the GUI is open -- farm farm = false, farmOpenChests = true, farmCompleteGame = true, -- OFF = chest-only mode: open chests, then rejoin farmSkipCutscene = true, farmRejoin = true, farmChestDelay = 0.2, farmAutoResume = true, -- resume automatically after rejoin (needs auto-execute) } local defaultGravity = Workspace.Gravity -- ========================================================= -- Proximity action core -- ========================================================= local function withProximity(targetPos: Vector3?, dist: number, action: () -> ()): boolean local root = getRoot() if not root or not targetPos then return false end local origin = root.CFrame local currentDist = (root.Position - targetPos).Magnitude if State.autoTp then if currentDist > dist + 1 then moveNear(targetPos, dist) task.wait(0.12) end else if currentDist > dist + 4 then return false end end action() if State.autoTp and State.returnAfter then task.wait(0.1) local r = getRoot() if r then r.AssemblyLinearVelocity = Vector3.zero r.CFrame = origin end end return true end -- ========================================================= -- Action loops -- ========================================================= task.spawn(function() while true do if State.autoScoop then if ensureBucketEquipped() and getBucketFill() < 1 then fire("Bucket.Used") end task.wait(math.max(State.scoopInterval, 0.05)) else task.wait(0.25) end end end) task.spawn(function() while true do if State.autoPour and getBucketFill() >= 1 then local prompt, pos = nearestPour() if prompt and pos then withProximity(pos, State.proximity, function() fire("Bucket.Poured", prompt) end) end task.wait(1) else task.wait(0.4) end end end) task.spawn(function() while true do if State.autoTokens then local prompt, pos = nearestPour() if prompt and pos then withProximity(pos, State.proximity, function() fire("Tokens.Take", prompt) end) end task.wait(1.5) else task.wait(0.4) end end end) task.spawn(function() while true do if State.autoChests then local chest, pos = nearestChest() if chest and pos then withProximity(pos, State.proximity, function() fire("Chest.Open", chest) end) task.wait(0.5) else task.wait(1.5) end else task.wait(0.5) end end end) -- ========================================================= -- Fly (client-side movers) -- ========================================================= local heldKeys: { [Enum.KeyCode]: boolean } = {} local flyBV: BodyVelocity? = nil local flyBG: BodyGyro? = nil local function stopFly() if flyBV then flyBV:Destroy() flyBV = nil end if flyBG then flyBG:Destroy() flyBG = nil end local h = getHumanoid() if h then h.PlatformStand = false end end local function startFly() local root = getRoot() if not root then return end stopFly() -- Legacy body movers remain the most broadly supported in injected clients. -- BodyGyro uses MaxTorque; assigning MaxForce is invalid and breaks Fly. flyBV = Instance.new("BodyVelocity") flyBV.Name = "BucketHubVelocity" flyBV.MaxForce = Vector3.new(1e6, 1e6, 1e6) flyBV.P = 1250 flyBV.Velocity = Vector3.zero flyBV.Parent = root flyBG = Instance.new("BodyGyro") flyBG.Name = "BucketHubGyro" flyBG.MaxTorque = Vector3.new(1e6, 1e6, 1e6) flyBG.P = 1e4 flyBG.D = 500 flyBG.CFrame = root.CFrame flyBG.Parent = root local h = getHumanoid() if h then h.PlatformStand = true end end -- ========================================================= -- Consolidated per-frame loop -- ========================================================= local hidePlayersDirty = false local survivalTick = 0 RunService.Heartbeat:Connect(function(dt) local humanoid = getHumanoid() if humanoid then if State.speedEnabled then humanoid.WalkSpeed = State.walkSpeed end if State.jumpEnabled then humanoid.UseJumpPower = true humanoid.JumpPower = State.jumpPower end if State.antiDeath and humanoid.Health < humanoid.MaxHealth then humanoid.Health = humanoid.MaxHealth end end -- Infinite Oxygen: pin the SwimController's internal meter every frame. -- This is the actual mechanism (no attributes involved). if State.infOxygen then local sc = findSwimController() if sc then sc._infiniteSwim = true if sc._meterMax and sc._swimMeter and sc._swimMeter < sc._meterMax then sc._swimMeter = sc._meterMax if sc._swimming then LocalPlayer:SetAttribute("SwimMeter", 1) end end cancelDrown(sc) end end -- Swim speed override if State.swimSpeedEnabled then local sc = findSwimController() if sc and sc._swimSpeed then sc._swimSpeed = State.swimSpeed end end -- Gravity override if State.gravityEnabled and math.abs(Workspace.Gravity - State.gravity) > 0.01 then Workspace.Gravity = State.gravity end -- Freeze character in place if State.freeze then local root = getRoot() if root then root.AssemblyLinearVelocity = Vector3.zero root.AssemblyAngularVelocity = Vector3.zero end end -- FOV enforcement if State.fovEnabled then local cam = Workspace.CurrentCamera if cam and math.abs(cam.FieldOfView - State.fov) > 0.5 then cam.FieldOfView = State.fov end end -- Throttled (4x/sec): oxygen attribute fallback + hide players survivalTick += dt if survivalTick >= 0.25 then survivalTick = 0 if State.infOxygen then pinOxygenAttributes(LocalPlayer) local char = getCharacter() if char then pinOxygenAttributes(char) end end if State.hidePlayers then for _, plr in Players:GetPlayers() do if plr ~= LocalPlayer and plr.Character then setCharacterHidden(plr.Character, true) end end hidePlayersDirty = true elseif hidePlayersDirty then hidePlayersDirty = false for _, plr in Players:GetPlayers() do if plr ~= LocalPlayer and plr.Character then setCharacterHidden(plr.Character, false) end end end end if State.fly and flyBV and flyBG then local cam = Workspace.CurrentCamera if cam then local dir = Vector3.zero if heldKeys[Enum.KeyCode.W] then dir += cam.CFrame.LookVector end if heldKeys[Enum.KeyCode.S] then dir -= cam.CFrame.LookVector end if heldKeys[Enum.KeyCode.A] then dir -= cam.CFrame.RightVector end if heldKeys[Enum.KeyCode.D] then dir += cam.CFrame.RightVector end if heldKeys[Enum.KeyCode.Space] then dir += Vector3.new(0, 1, 0) end if heldKeys[Enum.KeyCode.LeftControl] then dir -= Vector3.new(0, 1, 0) end flyBV.Velocity = dir.Magnitude > 0 and dir.Unit * State.flySpeed or Vector3.zero flyBG.CFrame = cam.CFrame end end end) RunService.Stepped:Connect(function() if State.noclip then local char = getCharacter() if char then for _, part in char:GetDescendants() do if part:IsA("BasePart") and part.CanCollide then part.CanCollide = false end end end end end) -- ========================================================= -- Anti-AFK -- ========================================================= task.spawn(function() local VirtualUser = game:GetService("VirtualUser") while true do if State.antiAfk then pcall(function() VirtualUser:CaptureController() VirtualUser:ClickButton2(Vector2.new()) end) task.wait(60) else task.wait(2) end end end) -- ========================================================= -- Fullbright -- ========================================================= local savedLighting: { [string]: any } = {} local function setFullbright(on: boolean) if on then savedLighting = { Brightness = Lighting.Brightness, ClockTime = Lighting.ClockTime, FogEnd = Lighting.FogEnd, GlobalShadows = Lighting.GlobalShadows, Ambient = Lighting.Ambient, OutdoorAmbient = Lighting.OutdoorAmbient, } Lighting.Brightness = 2 Lighting.ClockTime = 14 Lighting.FogEnd = 1e9 Lighting.GlobalShadows = false Lighting.Ambient = Color3.fromRGB(178, 178, 178) Lighting.OutdoorAmbient = Color3.fromRGB(178, 178, 178) else for k, v in savedLighting do pcall(function() (Lighting :: any)[k] = v end) end end end -- ========================================================= -- ESP (pooled Highlights + distance billboards) -- ========================================================= local espHolder = Instance.new("Folder") espHolder.Name = "BucketHubESP" espHolder.Parent = LocalPlayer:WaitForChild("PlayerGui") type EspEntry = { holder: Folder, label: TextLabel, target: Instance } type EspGroup = { enabled: boolean, color: Color3, name: string, entries: { [Instance]: EspEntry } } local espGroups: { [string]: EspGroup } = { Chest = { enabled = false, color = Color3.fromRGB(255, 196, 64), name = "Chest", entries = {} }, Pour = { enabled = false, color = Color3.fromRGB(64, 156, 255), name = "Drain", entries = {} }, Water = { enabled = false, color = Color3.fromRGB(80, 220, 200), name = "Water", entries = {} }, } local function espAdornTarget(inst: Instance): Instance? if inst:IsA("Model") or inst:IsA("BasePart") then return inst end return inst:FindFirstAncestorWhichIsA("Model") or inst:FindFirstAncestorWhichIsA("BasePart") end local function makeEspEntry(target: Instance, color: Color3, name: string): EspEntry? local adornee = espAdornTarget(target) if not adornee then return nil end local holder = Instance.new("Folder") holder.Name = "ESP_" .. name local hl = Instance.new("Highlight") hl.Adornee = adornee hl.FillColor = color hl.FillTransparency = 0.65 hl.OutlineColor = color hl.OutlineTransparency = 0 hl.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop hl.Parent = holder local bb = Instance.new("BillboardGui") bb.Size = UDim2.fromOffset(140, 26) bb.AlwaysOnTop = true bb.StudsOffset = Vector3.new(0, 3.5, 0) bb.MaxDistance = 2000 bb.Adornee = adornee bb.Parent = holder local label = Instance.new("TextLabel") label.Size = UDim2.fromScale(1, 1) label.BackgroundTransparency = 1 label.Font = Enum.Font.GothamBold label.TextSize = 13 label.TextColor3 = color label.TextStrokeTransparency = 0.4 label.Text = name label.Parent = bb holder.Parent = espHolder return { holder = holder, label = label, target = target } end local function clearEspGroup(group: EspGroup) for _, entry in group.entries do entry.holder:Destroy() end table.clear(group.entries) end local playerEsp: { [Player]: EspEntry } = {} local PLAYER_ESP_COLOR = Color3.fromRGB(235, 87, 87) local function clearPlayerEsp() for _, entry in playerEsp do entry.holder:Destroy() end table.clear(playerEsp) end task.spawn(function() while espHolder.Parent do local root = getRoot() for tag, group in espGroups do if group.enabled then local live: { [Instance]: boolean } = {} for _, inst in CollectionService:GetTagged(tag) do live[inst] = true if not group.entries[inst] then local entry = makeEspEntry(inst, group.color, group.name) if entry then group.entries[inst] = entry end end end for inst, entry in group.entries do if not live[inst] or inst.Parent == nil then entry.holder:Destroy() group.entries[inst] = nil elseif root then local pos = instancePosition(inst) if pos then entry.label.Text = ("%s — %dm"):format(group.name, math.floor((pos - root.Position).Magnitude)) end end end elseif next(group.entries) ~= nil then clearEspGroup(group) end end if State.espPlayers then for _, plr in Players:GetPlayers() do if plr ~= LocalPlayer then local char = plr.Character local entry = playerEsp[plr] if char and (not entry or entry.target ~= char) then if entry then entry.holder:Destroy() end local newEntry = makeEspEntry(char, PLAYER_ESP_COLOR, plr.Name) if newEntry then playerEsp[plr] = newEntry end elseif entry and root and char then local pos = instancePosition(char) if pos then entry.label.Text = ("%s — %dm"):format(plr.Name, math.floor((pos - root.Position).Magnitude)) end end end end for plr, entry in playerEsp do if plr.Parent == nil or plr.Character == nil then entry.holder:Destroy() playerEsp[plr] = nil end end elseif next(playerEsp) ~= nil then clearPlayerEsp() end task.wait(1) end end) -- ========================================================= -- Waypoints -- ========================================================= local savedWaypoint: CFrame? = nil -- ========================================================= -- Skill tree auto-buy -- ========================================================= local function getSkillNodes(): { [string]: { [string]: any } } local ok, SkillEffects = pcall(function() return require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("Registry"):WaitForChild("SkillEffects")) end) if ok and type(SkillEffects) == "table" and type(SkillEffects.NODES) == "table" then return SkillEffects.NODES end return {} end local function parseCoord(key: string): (number?, number?) local xs, ys = string.match(key, "^(-?%d+),(-?%d+)$") return tonumber(xs), tonumber(ys) end local function autoBuySkills(filterKey: string?, statusCallback: (string) -> ()) local nodes = getSkillNodes() if next(nodes) == nil then statusCallback("SkillEffects.NODES not found") return end local bought = 0 for pass = 1, 5 do local anyThisPass = false for treeId, tree in nodes do for coord, node in tree do if filterKey == nil or node.key == filterKey then local x, y = parseCoord(coord) if x and y then local result = invoke("SkillTree.Purchase", treeId, x, y) if type(result) == "table" and result.ok then bought += 1 anyThisPass = true statusCallback(("Bought %s [%s] (pass %d)"):format(tostring(treeId), coord, pass)) task.wait(0.12) end end end end end if not anyThisPass then break end end statusCallback(("Done — %d node(s) purchased"):format(bought)) end -- ========================================================= -- FARM engine -- ========================================================= -- Full lake-run loop: inf oxygen -> open all chests -> trigger the ending -- door at the bottom of the map -> auto-vote YES -> skip cutscene -> end -- screen (gems awarded) -> rejoin -> repeat (via auto-execute + persistence). local farmSetStatus: (string) -> () = function(_) end -- rebound to the GUI status bar later local setInfOxygenToggle: ((boolean) -> ())? = nil -- assigned when the toggles are built local setAntiDeathToggle: ((boolean) -> ())? = nil local Farm = { step = "idle", doorPos = nil :: Vector3?, -- manually saved door position (persisted) voteSeen = false, -- Ending.VoteStart received endScreenSeen = false, -- ShowEndScreen received (gems given) cutsceneSessionId = nil :: any, -- from CutscenePrepare, used for vote-skip runs = 0, } local function farmLog(msg: string) Farm.step = msg farmSetStatus("[Farm] " .. msg) print("[BucketHub Farm] " .. msg) end -- ---- executor helpers (all optional, everything degrades gracefully) ---- local function exGlobal(name: string): any local ok, v = pcall(function() return (getfenv() :: any)[name] end) if ok and v ~= nil then return v end local ok2, v2 = pcall(function() return (getgenv :: any)()[name] end) if ok2 then return v2 end return nil end local FARM_FILE = "buckethub_farm.json" local function farmSaveState() local writefileFn = exGlobal("writefile") if not writefileFn then return end local HttpService = game:GetService("HttpService") pcall(function() writefileFn(FARM_FILE, HttpService:JSONEncode({ farm = State.farm, openChests = State.farmOpenChests, completeGame = State.farmCompleteGame, skipCutscene = State.farmSkipCutscene, rejoin = State.farmRejoin, chestDelay = State.farmChestDelay, runs = Farm.runs, doorPos = Farm.doorPos and { Farm.doorPos.X, Farm.doorPos.Y, Farm.doorPos.Z } or nil, placeId = game.PlaceId, })) end) end local function farmLoadState(): boolean local readfileFn = exGlobal("readfile") local isfileFn = exGlobal("isfile") if not readfileFn then return false end if isfileFn and not isfileFn(FARM_FILE) then return false end local HttpService = game:GetService("HttpService") local ok, data = pcall(function() return HttpService:JSONDecode(readfileFn(FARM_FILE)) end) if not ok or type(data) ~= "table" then return false end if data.placeId ~= game.PlaceId then return false -- different game (e.g. we are back in the lobby place) end if type(data.doorPos) == "table" and #data.doorPos == 3 then Farm.doorPos = Vector3.new(data.doorPos[1], data.doorPos[2], data.doorPos[3]) end if data.openChests ~= nil then State.farmOpenChests = data.openChests == true end if data.completeGame ~= nil then State.farmCompleteGame = data.completeGame == true end if data.skipCutscene ~= nil then State.farmSkipCutscene = data.skipCutscene == true end if data.rejoin ~= nil then State.farmRejoin = data.rejoin == true end if tonumber(data.chestDelay) then State.farmChestDelay = math.clamp(tonumber(data.chestDelay), 0.1, 1.5) end Farm.runs = tonumber(data.runs) or 0 return data.farm == true end -- Restore options before controls are created so the UI opens in sync. local savedFarmWasRunning = State.farmAutoResume and farmLoadState() -- ---- auto-execute / rejoin persistence ---- -- The script cannot read its own source, so it reloads from either: -- a) getgenv().BUCKET_HUB_URL (a raw URL to this script), or -- b) a saved copy at /buckethub.lua (save it once). -- With either in place, the farm installs an autoexec loader AND queues -- itself with queue_on_teleport, so it is back automatically next game. local HUB_FILES = { "buckethub-v4.lua", "buckethub.lua" } local function farmGetLoader(): string? local url = environment.BUCKET_HUB_URL or exGlobal("BUCKET_HUB_URL") if type(url) == "string" and #url > 0 then return ('task.wait(2); loadstring(game:HttpGet(%q), "Bucket Hub v4")()'):format(url) end local isfileFn = exGlobal("isfile") if isfileFn then for _, path in HUB_FILES do local ok, exists = pcall(isfileFn, path) if ok and exists then return ('task.wait(2); if isfile(%q) then loadstring(readfile(%q), "Bucket Hub v4")() end'):format(path, path) end end end return nil end local function farmInstallAutoExec(): boolean local writefileFn = exGlobal("writefile") local makefolderFn = exGlobal("makefolder") local loader = farmGetLoader() if not writefileFn or not loader then return false end if makefolderFn then pcall(makefolderFn, "autoexec") end return pcall(writefileFn, "autoexec/buckethub-v4-loader.lua", loader) == true end local function farmQueueOnTeleport(): boolean local synTable = exGlobal("syn") local fluxusTable = exGlobal("fluxus") local qot = exGlobal("queue_on_teleport") or exGlobal("queueonteleport") or (type(synTable) == "table" and synTable.queue_on_teleport) or (type(fluxusTable) == "table" and fluxusTable.queue_on_teleport) local loader = farmGetLoader() if type(qot) ~= "function" or not loader then return false end return pcall(qot, loader) == true end -- ---- prompt triggering ---- local function firePrompt(prompt: ProximityPrompt): boolean local fpp = exGlobal("fireproximityprompt") if fpp then local ok = pcall(fpp, prompt) if ok then return true end end -- legit fallback: simulate the hold from the client local ok = pcall(function() prompt:InputHoldBegin() if prompt.HoldDuration > 0 then task.wait(prompt.HoldDuration + 0.1) end prompt:InputHoldEnd() end) return ok end -- ---- ending-door discovery ---- -- The end door is the ProximityPrompt at the very BOTTOM of the map that is -- not a chest / drain / skill tree / another player's prompt. local function isFarmIgnoredPrompt(prompt: ProximityPrompt): boolean local node: Instance? = prompt while node and node ~= Workspace do if CollectionService:HasTag(node, "Chest") or CollectionService:HasTag(node, "Pour") or CollectionService:HasTag(node, "Water") or CollectionService:HasTag(node, "SkillTree") then return true end node = node.Parent end -- ignore prompts inside any character local model = prompt:FindFirstAncestorWhichIsA("Model") if model and Players:GetPlayerFromCharacter(model) then return true end return false end local function findEndDoorPrompt(): (ProximityPrompt?, Vector3?) -- 1) manually saved position wins: use the prompt closest to it if Farm.doorPos then local best: ProximityPrompt? = nil local bestDist = math.huge for _, inst in Workspace:GetDescendants() do if inst:IsA("ProximityPrompt") then local pos = instancePosition(inst) if pos then local d = (pos - Farm.doorPos).Magnitude if d < bestDist then bestDist = d best = inst end end end end if best and bestDist < 30 then return best, instancePosition(best) end -- prompt may not exist yet/anymore; still return the position so we -- can swim there (it may stream in / be recreated) return nil, Farm.doorPos end -- 2) heuristic: lowest prompt on the map local best: ProximityPrompt? = nil local bestPos: Vector3? = nil local bestY = math.huge for _, inst in Workspace:GetDescendants() do if inst:IsA("ProximityPrompt") and not isFarmIgnoredPrompt(inst) then local pos = instancePosition(inst) if pos and pos.Y < bestY then bestY = pos.Y best = inst bestPos = pos end end end return best, bestPos end -- ---- remote listeners (auto-vote YES, skip cutscene, detect end screen) ---- task.spawn(function() local r = getRemote("Ending.VoteStart") if r and r:IsA("RemoteEvent") then r.OnClientEvent:Connect(function() Farm.voteSeen = true if State.farm then task.wait(0.4) fire("Ending.VoteCast", true) farmLog("Ending vote started — voted YES") end end) end end) task.spawn(function() local r = getRemote("CutscenePrepare") if r and r:IsA("RemoteEvent") then r.OnClientEvent:Connect(function(payload) if type(payload) == "table" then Farm.cutsceneSessionId = payload.id or payload.sessionId end end) end end) task.spawn(function() local r = getRemote("CutsceneStart") if r and r:IsA("RemoteEvent") then r.OnClientEvent:Connect(function(payload) if type(payload) == "table" then Farm.cutsceneSessionId = payload.id or payload.sessionId or Farm.cutsceneSessionId end if State.farm and State.farmSkipCutscene then task.spawn(function() -- vote to skip a few times (EndingTwo SkipMode = Vote, threshold 1) for _ = 1, 5 do task.wait(1.5) if Farm.cutsceneSessionId then fire("CutsceneVoteSkip", Farm.cutsceneSessionId) end if Farm.endScreenSeen then break end end end) farmLog("Cutscene started — vote-skipping") end end) end end) task.spawn(function() local r = getRemote("ShowEndScreen") if r and r:IsA("RemoteEvent") then r.OnClientEvent:Connect(function() Farm.endScreenSeen = true if State.farm then farmLog("End screen — gems awarded!") end end) end end) -- ---- farm steps ---- local function farmWaitFor(check: () -> boolean, timeout: number): boolean local deadline = os.clock() + timeout while os.clock() < deadline do if not State.farm then return false end if check() then return true end task.wait(0.2) end return check() end local function farmOpenAllChests() local chests = CollectionService:GetTagged("Chest") table.sort(chests, function(a, b) local pa, pb = instancePosition(a), instancePosition(b) return (pa and pa.Y or 0) > (pb and pb.Y or 0) -- top-down toward the door end) local opened = 0 for i, chest in chests do if not State.farm then return end local prompt = promptFor(chest) local pos = instancePosition(chest) if pos and (prompt == nil or prompt.Enabled) then farmLog(("Opening chest %d/%d"):format(i, #chests)) moveNear(pos, 5) task.wait(0.15) fire("Chest.Open", chest) -- wait for the server's Chest.Opened to disable the prompt local okOpen = prompt and farmWaitFor(function() return not prompt.Enabled end, 2.5) or false if not okOpen and prompt then firePrompt(prompt) -- fallback: trigger the prompt itself farmWaitFor(function() return not prompt.Enabled end, 2) end opened += 1 task.wait(math.max(State.farmChestDelay, 0.1)) end end farmLog(("Chests done (%d opened)"):format(opened)) end local function farmTriggerDoor(): boolean for attempt = 1, 6 do if not State.farm then return false end local prompt, pos = findEndDoorPrompt() if not pos then farmLog("End door not found — swim to it once and press 'Set End Door Here'") task.wait(3) else farmLog(("Diving to end door (attempt %d)"):format(attempt)) moveNear(pos, 4) task.wait(0.3) if prompt then firePrompt(prompt) end -- success = vote starts, cutscene starts, or end screen appears if farmWaitFor(function() return Farm.voteSeen or Farm.endScreenSeen or Farm.cutsceneSessionId ~= nil end, 6) then return true end end end return false end local function farmRejoinServer() farmSaveState() local TeleportService = game:GetService("TeleportService") local installed = farmInstallAutoExec() local queued = farmQueueOnTeleport() if queued or installed then farmLog("Rejoining (script will auto-load next game)...") else farmLog("Rejoining — NO loader found! Save this script as 'buckethub.lua' in your executor workspace (or set getgenv().BUCKET_HUB_URL) so it can reload itself") end task.wait(1) pcall(function() TeleportService:Teleport(game.PlaceId, LocalPlayer) end) end local function farmRunCycle() Farm.voteSeen = false Farm.endScreenSeen = false Farm.cutsceneSessionId = nil -- step 1: survival on State.infOxygen = true if setInfOxygenToggle then setInfOxygenToggle(true) end State.antiDeath = true if setAntiDeathToggle then setAntiDeathToggle(true) end farmLog("Infinite oxygen + anti-death on") -- wait for a live character if not farmWaitFor(function() local h = getHumanoid() return h ~= nil and h.Health > 0 and getRoot() ~= nil end, 30) then return end task.wait(0.5) -- step 2: chests if State.farmOpenChests and State.farm then farmOpenAllChests() end if not State.farm then return end -- chest-only mode: skip the ending entirely, just rejoin and repeat if not State.farmCompleteGame then Farm.runs += 1 farmLog(("Chest run #%d done — rejoining"):format(Farm.runs)) task.wait(1) if State.farmRejoin then farmRejoinServer() task.wait(15) else farmLog("Rejoin disabled — chest run done, farm idle") task.wait(10) end return end -- step 3: the ending door if not farmTriggerDoor() then -- don't restart the cycle — just rejoin and try fresh next game if State.farmRejoin then farmLog("End door failed — rejoining for a fresh run") task.wait(1) farmRejoinServer() task.wait(15) else farmLog("End door failed and rejoin is off — farm idle") task.wait(10) end return end -- step 4: ride out vote + cutscene until the end screen (gems) farmLog("Waiting for ending (vote/cutscene)...") farmWaitFor(function() return Farm.endScreenSeen end, 150) if not State.farm then return end if Farm.endScreenSeen then Farm.runs += 1 farmLog(("Run #%d complete — gems collected"):format(Farm.runs)) task.wait(2.5) -- let rewards settle -- step 5: rejoin if State.farmRejoin then farmRejoinServer() task.wait(15) -- teleport takes over from here else farmLog("Rejoin disabled — farm idle (waiting for you)") task.wait(10) end else farmLog("Ending never fired — retrying") task.wait(5) end end -- main farm loop task.spawn(function() while true do if State.farm then local ok, err = pcall(farmRunCycle) if not ok then farmLog("Error: " .. tostring(err)) task.wait(3) end task.wait(0.5) else task.wait(0.6) end end end) -- ========================================================= -- Theme + GUI construction -- ========================================================= local THEME = { bg = Color3.fromRGB(10, 14, 20), panel = Color3.fromRGB(17, 23, 32), panelLight = Color3.fromRGB(28, 37, 49), accent = Color3.fromRGB(36, 199, 151), accentOff = Color3.fromRGB(51, 63, 76), text = Color3.fromRGB(239, 244, 248), textDim = Color3.fromRGB(139, 153, 168), danger = Color3.fromRGB(224, 82, 82), } local gui = Instance.new("ScreenGui") gui.Name = "BucketHub" gui.ResetOnSpawn = false gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling gui.Parent = LocalPlayer:WaitForChild("PlayerGui") local main = Instance.new("Frame") main.Name = "Main" main.Size = UDim2.fromOffset(560, 520) main.Position = UDim2.new(0, 24, 0.5, -260) main.BackgroundColor3 = THEME.bg main.BorderSizePixel = 0 main.Active = true main.Parent = gui local mainCorner = Instance.new("UICorner") mainCorner.CornerRadius = UDim.new(0, 10) mainCorner.Parent = main local stroke = Instance.new("UIStroke") stroke.Color = THEME.panelLight stroke.Thickness = 1 stroke.Parent = main -- Title bar (draggable) local titleBar = Instance.new("Frame") titleBar.Name = "TitleBar" titleBar.Size = UDim2.new(1, 0, 0, 40) titleBar.BackgroundColor3 = THEME.panel titleBar.BorderSizePixel = 0 titleBar.Parent = main local titleCorner = Instance.new("UICorner") titleCorner.CornerRadius = UDim.new(0, 10) titleCorner.Parent = titleBar local title = Instance.new("TextLabel") title.Size = UDim2.new(1, -90, 1, 0) title.Position = UDim2.fromOffset(12, 0) title.BackgroundTransparency = 1 title.Font = Enum.Font.GothamBold title.TextSize = 16 title.TextColor3 = THEME.text title.TextXAlignment = Enum.TextXAlignment.Left title.Text = "BUCKET HUB / CONTROL DECK" title.Parent = titleBar local fillLabel = Instance.new("TextLabel") fillLabel.Size = UDim2.fromOffset(80, 40) fillLabel.Position = UDim2.new(1, -86, 0, 0) fillLabel.BackgroundTransparency = 1 fillLabel.Font = Enum.Font.GothamMedium fillLabel.TextSize = 12 fillLabel.TextColor3 = THEME.accent fillLabel.Text = "Fill: 0%" fillLabel.Parent = titleBar -- drag logic do local dragging = false local dragStart: Vector3 local startPos: UDim2 titleBar.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = main.Position end end) UserInputService.InputChanged:Connect(function(input) if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then local delta = input.Position - dragStart main.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) end end) UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end end) end -- Sidebar navigation local tabBar = Instance.new("Frame") tabBar.Size = UDim2.new(0, 126, 1, -86) tabBar.Position = UDim2.fromOffset(10, 52) tabBar.BackgroundColor3 = THEME.panel tabBar.BorderSizePixel = 0 tabBar.Parent = main local tabBarCorner = Instance.new("UICorner") tabBarCorner.CornerRadius = UDim.new(0, 8) tabBarCorner.Parent = tabBar local tabBarPadding = Instance.new("UIPadding") tabBarPadding.PaddingTop = UDim.new(0, 8) tabBarPadding.PaddingLeft = UDim.new(0, 8) tabBarPadding.PaddingRight = UDim.new(0, 8) tabBarPadding.Parent = tabBar local tabLayout = Instance.new("UIListLayout") tabLayout.FillDirection = Enum.FillDirection.Vertical tabLayout.Padding = UDim.new(0, 6) tabLayout.Parent = tabBar -- Status bar local statusLabel = Instance.new("TextLabel") statusLabel.Size = UDim2.new(1, -156, 0, 20) statusLabel.Position = UDim2.new(0, 146, 1, -26) statusLabel.BackgroundTransparency = 1 statusLabel.Font = Enum.Font.Gotham statusLabel.TextSize = 11 statusLabel.TextColor3 = THEME.textDim statusLabel.TextXAlignment = Enum.TextXAlignment.Left statusLabel.TextTruncate = Enum.TextTruncate.AtEnd statusLabel.Text = "Ready — LeftAlt toggles the GUI" statusLabel.Parent = main local function setStatus(text: string) statusLabel.Text = text end -- Tab pages local pages: { [string]: ScrollingFrame } = {} local tabButtons: { [string]: TextButton } = {} local function selectTab(name: string) for tabName, page in pages do page.Visible = tabName == name tabButtons[tabName].BackgroundColor3 = tabName == name and THEME.accent or THEME.panelLight tabButtons[tabName].TextColor3 = tabName == name and THEME.bg or THEME.textDim end end local function makeTab(name: string): ScrollingFrame local btn = Instance.new("TextButton") btn.Size = UDim2.new(1, 0, 0, 38) btn.BackgroundColor3 = THEME.panelLight btn.Font = Enum.Font.GothamMedium btn.TextSize = 12 btn.TextColor3 = THEME.textDim btn.TextXAlignment = Enum.TextXAlignment.Left btn.Text = " " .. name btn.AutoButtonColor = false btn.Parent = tabBar local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, 6) c.Parent = btn local page = Instance.new("ScrollingFrame") page.Size = UDim2.new(1, -156, 1, -92) page.Position = UDim2.fromOffset(146, 52) page.BackgroundTransparency = 1 page.BorderSizePixel = 0 page.ScrollBarThickness = 4 page.ScrollBarImageColor3 = THEME.accentOff page.AutomaticCanvasSize = Enum.AutomaticSize.Y page.CanvasSize = UDim2.new() page.Visible = false page.Parent = main local layout = Instance.new("UIListLayout") layout.Padding = UDim.new(0, 6) layout.SortOrder = Enum.SortOrder.LayoutOrder layout.Parent = page pages[name] = page tabButtons[name] = btn btn.MouseButton1Click:Connect(function() selectTab(name) end) return page end -- Control factories -------------------------------------------------------- -- makeToggle now RETURNS a setter so hotkeys can flip toggles and keep the -- GUI knob in sync. local function makeToggle(parent: Instance, label: string, initial: boolean, onChanged: (boolean) -> ()): (boolean) -> () local row = Instance.new("Frame") row.Size = UDim2.new(1, 0, 0, 34) row.BackgroundColor3 = THEME.panel row.BorderSizePixel = 0 row.Parent = parent local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, 6) c.Parent = row local text = Instance.new("TextLabel") text.Size = UDim2.new(1, -66, 1, 0) text.Position = UDim2.fromOffset(10, 0) text.BackgroundTransparency = 1 text.Font = Enum.Font.GothamMedium text.TextSize = 13 text.TextColor3 = THEME.text text.TextXAlignment = Enum.TextXAlignment.Left text.Text = label text.Parent = row local state = initial local knobBg = Instance.new("TextButton") knobBg.Size = UDim2.fromOffset(44, 22) knobBg.Position = UDim2.new(1, -54, 0.5, -11) knobBg.BackgroundColor3 = state and THEME.accent or THEME.accentOff knobBg.Text = "" knobBg.AutoButtonColor = false knobBg.Parent = row local kc = Instance.new("UICorner") kc.CornerRadius = UDim.new(1, 0) kc.Parent = knobBg local knob = Instance.new("Frame") knob.Size = UDim2.fromOffset(16, 16) knob.Position = state and UDim2.new(1, -19, 0.5, -8) or UDim2.new(0, 3, 0.5, -8) knob.BackgroundColor3 = Color3.fromRGB(255, 255, 255) knob.Parent = knobBg local kc2 = Instance.new("UICorner") kc2.CornerRadius = UDim.new(1, 0) kc2.Parent = knob local function apply(newState: boolean) state = newState knobBg.BackgroundColor3 = state and THEME.accent or THEME.accentOff knob.Position = state and UDim2.new(1, -19, 0.5, -8) or UDim2.new(0, 3, 0.5, -8) onChanged(state) end knobBg.MouseButton1Click:Connect(function() apply(not state) end) return apply end local function makeSlider(parent: Instance, label: string, min: number, max: number, initial: number, decimals: number, onChanged: (number) -> ()) local row = Instance.new("Frame") row.Size = UDim2.new(1, 0, 0, 48) row.BackgroundColor3 = THEME.panel row.BorderSizePixel = 0 row.Parent = parent local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, 6) c.Parent = row local fmt = "%." .. tostring(decimals) .. "f" local text = Instance.new("TextLabel") text.Size = UDim2.new(1, -20, 0, 20) text.Position = UDim2.fromOffset(10, 4) text.BackgroundTransparency = 1 text.Font = Enum.Font.GothamMedium text.TextSize = 13 text.TextColor3 = THEME.text text.TextXAlignment = Enum.TextXAlignment.Left text.Text = label .. ": " .. string.format(fmt, initial) text.Parent = row local track = Instance.new("TextButton") track.Size = UDim2.new(1, -20, 0, 8) track.Position = UDim2.fromOffset(10, 30) track.BackgroundColor3 = THEME.accentOff track.Text = "" track.AutoButtonColor = false track.Parent = row local tc = Instance.new("UICorner") tc.CornerRadius = UDim.new(1, 0) tc.Parent = track local fillBar = Instance.new("Frame") fillBar.Size = UDim2.new((initial - min) / (max - min), 0, 1, 0) fillBar.BackgroundColor3 = THEME.accent fillBar.BorderSizePixel = 0 fillBar.Parent = track local fc = Instance.new("UICorner") fc.CornerRadius = UDim.new(1, 0) fc.Parent = fillBar local draggingSlider = false local function update(inputPos: Vector2) local rel = math.clamp((inputPos.X - track.AbsolutePosition.X) / track.AbsoluteSize.X, 0, 1) local value = min + (max - min) * rel fillBar.Size = UDim2.new(rel, 0, 1, 0) text.Text = label .. ": " .. string.format(fmt, value) onChanged(value) end track.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then draggingSlider = true update(Vector2.new(input.Position.X, input.Position.Y)) end end) UserInputService.InputChanged:Connect(function(input) if draggingSlider and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then update(Vector2.new(input.Position.X, input.Position.Y)) end end) UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then draggingSlider = false end end) end local function makeButton(parent: Instance, label: string, danger: boolean, onClick: () -> ()): TextButton local btn = Instance.new("TextButton") btn.Size = UDim2.new(1, 0, 0, 32) btn.BackgroundColor3 = danger and THEME.danger or THEME.panelLight btn.Font = Enum.Font.GothamBold btn.TextSize = 13 btn.TextColor3 = THEME.text btn.Text = label btn.Parent = parent local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, 6) c.Parent = btn btn.MouseButton1Click:Connect(function() task.spawn(onClick) end) return btn end local function makeSection(parent: Instance, label: string) local text = Instance.new("TextLabel") text.Size = UDim2.new(1, 0, 0, 18) text.BackgroundTransparency = 1 text.Font = Enum.Font.GothamBold text.TextSize = 11 text.TextColor3 = THEME.textDim text.TextXAlignment = Enum.TextXAlignment.Left text.Text = string.upper(label) text.Parent = parent end -- ========================================================= -- GUI open/close + first-person mouse unlock -- ========================================================= local function setGuiOpen(open: boolean) main.Visible = open if not open then -- give mouse control back to the game (first-person re-locks itself) UserInputService.MouseIconEnabled = true end end -- While the GUI is open, force the cursor free every render step — -- first-person camera scripts re-lock it every frame, so we out-stubborn them. RunService:BindToRenderStep("BucketHubMouseUnlock", Enum.RenderPriority.Last.Value + 1, function() if main.Visible and State.unlockMouse then UserInputService.MouseBehavior = Enum.MouseBehavior.Default UserInputService.MouseIconEnabled = true end end) -- ========================================================= -- Build tabs -- ========================================================= local farmPage = makeTab("Farm") local actionsPage = makeTab("Actions") local playerPage = makeTab("Player") local visualsPage = makeTab("Visuals") local skillsPage = makeTab("Skills") local serverPage = makeTab("Server") local settingsPage = makeTab("Config") -- hook the farm engine into the status bar now that it exists farmSetStatus = setStatus -- FARM ---------------------------------------------------- makeSection(farmPage, "Lake Auto-Farm") local farmStepLabel = Instance.new("TextLabel") farmStepLabel.Size = UDim2.new(1, 0, 0, 40) farmStepLabel.BackgroundColor3 = THEME.panel farmStepLabel.BorderSizePixel = 0 farmStepLabel.Font = Enum.Font.GothamMedium farmStepLabel.TextSize = 12 farmStepLabel.TextColor3 = THEME.accent farmStepLabel.TextXAlignment = Enum.TextXAlignment.Left farmStepLabel.TextWrapped = true farmStepLabel.Text = " Idle — turn the farm on to start" farmStepLabel.Parent = farmPage do local fc = Instance.new("UICorner") fc.CornerRadius = UDim.new(0, 6) fc.Parent = farmStepLabel end task.spawn(function() while farmStepLabel.Parent do farmStepLabel.Text = (" Step: %s\n Runs completed: %d"):format(Farm.step, Farm.runs) task.wait(0.5) end end) local setFarmToggle = makeToggle(farmPage, "AUTO FARM (full loop)", false, function(on) State.farm = on if on then Farm.voteSeen = false Farm.endScreenSeen = false farmLog("Farm started") else farmLog("Farm stopped") end farmSaveState() end) makeSection(farmPage, "Steps") makeToggle(farmPage, "1. Open All Chests", State.farmOpenChests, function(on) State.farmOpenChests = on farmSaveState() end) makeToggle(farmPage, "2. Complete Game (end door + gems)", State.farmCompleteGame, function(on) State.farmCompleteGame = on farmSaveState() setStatus(on and "Full runs: chests + ending + gems" or "Chest-only mode: open chests, then rejoin") end) makeToggle(farmPage, "3. Skip Ending Cutscene", State.farmSkipCutscene, function(on) State.farmSkipCutscene = on farmSaveState() end) makeToggle(farmPage, "4. Rejoin When Done", State.farmRejoin, function(on) State.farmRejoin = on farmSaveState() end) makeSlider(farmPage, "Chest Delay (s)", 0.1, 1.5, State.farmChestDelay, 2, function(v) State.farmChestDelay = v end) makeSection(farmPage, "End Door") makeButton(farmPage, "Set End Door Here (stand at it once)", false, function() local root = getRoot() if not root then return end -- snap to the nearest prompt if one is close, else save raw position local bestPos: Vector3? = nil local bestDist = math.huge for _, inst in Workspace:GetDescendants() do if inst:IsA("ProximityPrompt") then local pos = instancePosition(inst) if pos then local d = (pos - root.Position).Magnitude if d < bestDist then bestDist = d bestPos = pos end end end end Farm.doorPos = (bestPos and bestDist < 25) and bestPos or root.Position farmSaveState() setStatus(("End door saved at (%d, %d, %d)"):format(Farm.doorPos.X, Farm.doorPos.Y, Farm.doorPos.Z)) end) makeButton(farmPage, "Clear Saved Door (use auto-detect)", false, function() Farm.doorPos = nil farmSaveState() setStatus("Saved door cleared — auto-detect (lowest prompt) will be used") end) makeButton(farmPage, "Test: Dive To End Door Now", false, function() local prompt, pos = findEndDoorPrompt() if pos then moveNear(pos, 4) setStatus(prompt and "At the end door (prompt found)" or "At saved position (no prompt seen yet)") else setStatus("No door found — stand at it and press 'Set End Door Here'") end end) makeSection(farmPage, "Manual Steps (for testing)") makeButton(farmPage, "Open All Chests Now", false, function() setStatus("Opening all chests...") farmOpenAllChests() end) makeButton(farmPage, "Trigger Ending Now", false, function() Farm.voteSeen = false setStatus("Triggering ending...") if farmTriggerDoor() then fire("Ending.VoteCast", true) setStatus("Ending triggered — voted YES") else setStatus("Could not trigger the ending door") end end) makeButton(farmPage, "Vote YES On Ending Now", false, function() fire("Ending.VoteCast", true) setStatus("Voted YES on the ending") end) do local note = Instance.new("TextLabel") note.Size = UDim2.new(1, 0, 0, 74) note.BackgroundColor3 = THEME.panel note.BorderSizePixel = 0 note.Font = Enum.Font.Gotham note.TextSize = 11 note.TextColor3 = THEME.textDim note.TextXAlignment = Enum.TextXAlignment.Left note.TextYAlignment = Enum.TextYAlignment.Top note.TextWrapped = true note.Text = " REJOIN RELOAD: save this file as buckethub-v4.lua, or set getgenv().BUCKET_HUB_URL to its raw URL. Active farm runs resume after teleport when your executor supports queueing." note.Parent = farmPage local nc = Instance.new("UICorner") nc.CornerRadius = UDim.new(0, 6) nc.Parent = note end -- ACTIONS ------------------------------------------------- makeSection(actionsPage, "Scooping") makeToggle(actionsPage, "Auto Scoop", false, function(on) State.autoScoop = on setStatus(on and "Auto Scoop enabled" or "Auto Scoop disabled") end) makeSlider(actionsPage, "Scoop Interval (s)", 0.05, 0.6, State.scoopInterval, 2, function(v) State.scoopInterval = v end) makeSection(actionsPage, "Draining & Tokens (proximity)") makeToggle(actionsPage, "Auto Pour When Full", false, function(on) State.autoPour = on setStatus(on and "Auto Pour enabled" or "Auto Pour disabled") end) makeToggle(actionsPage, "Auto Collect Tokens", false, function(on) State.autoTokens = on setStatus(on and "Auto Collect enabled" or "Auto Collect disabled") end) makeButton(actionsPage, "Pour Now (nearest drain)", false, function() local prompt, pos = nearestPour() if prompt and pos then local ok = withProximity(pos, State.proximity, function() fire("Bucket.Poured", prompt) end) setStatus(ok and "Poured at nearest drain" or "Too far — enable Auto-TP") else setStatus("No drain station found") end end) makeButton(actionsPage, "Collect Tokens Now", false, function() local prompt, pos = nearestPour() if prompt and pos then local ok = withProximity(pos, State.proximity, function() fire("Tokens.Take", prompt) end) setStatus(ok and "Collected tokens" or "Too far — enable Auto-TP") else setStatus("No drain station found") end end) makeSection(actionsPage, "Chests (proximity)") makeToggle(actionsPage, "Auto Open Chests", false, function(on) State.autoChests = on setStatus(on and "Auto Chests enabled" or "Auto Chests disabled") end) makeButton(actionsPage, "Open Nearest Chest", false, function() local chest, pos = nearestChest() if chest and pos then local ok = withProximity(pos, State.proximity, function() fire("Chest.Open", chest) end) setStatus(ok and "Opened nearest chest" or "Too far — enable Auto-TP") else setStatus("No openable chest found") end end) makeButton(actionsPage, "Open ALL Chests", false, function() local count = 0 for _, chest in CollectionService:GetTagged("Chest") do local pos = instancePosition(chest) local prompt = promptFor(chest) if pos and (prompt == nil or prompt.Enabled) then withProximity(pos, State.proximity, function() fire("Chest.Open", chest) end) count += 1 task.wait(0.35) end end setStatus(("Opened %d chest(s)"):format(count)) end) makeSection(actionsPage, "Proximity Settings") makeToggle(actionsPage, "Auto-TP To Targets", true, function(on) State.autoTp = on setStatus(on and "Auto-TP on — will teleport to targets" or "Auto-TP off — act only when close") end) makeToggle(actionsPage, "Return After Action", false, function(on) State.returnAfter = on end) makeSlider(actionsPage, "Stand-off Distance", 3, 14, State.proximity, 0, function(v) State.proximity = v end) makeButton(actionsPage, "Teleport To Water", false, function() local _, pos = nearestTaggedPos("Water") if pos then teleportTo(pos + Vector3.new(0, 4, 0)) setStatus("Teleported to nearest water") else setStatus("No tagged water found") end end) -- PLAYER -------------------------------------------------- makeSection(playerPage, "Movement") makeToggle(playerPage, "Walk Speed Override", false, function(on) State.speedEnabled = on if not on then local h = getHumanoid() if h then h.WalkSpeed = 16 end end end) makeSlider(playerPage, "Walk Speed", 16, 250, State.walkSpeed, 0, function(v) State.walkSpeed = v end) makeToggle(playerPage, "Jump Power Override", false, function(on) State.jumpEnabled = on if not on then local h = getHumanoid() if h then h.JumpPower = 50 end end end) makeSlider(playerPage, "Jump Power", 50, 350, State.jumpPower, 0, function(v) State.jumpPower = v end) makeToggle(playerPage, "Infinite Jump", false, function(on) State.infiniteJump = on end) local setNoclipToggle = makeToggle(playerPage, "Noclip (N)", false, function(on) State.noclip = on setStatus(on and "Noclip on — you can pass through parts" or "Noclip off") end) makeToggle(playerPage, "Gravity Override", false, function(on) State.gravityEnabled = on if not on then Workspace.Gravity = defaultGravity end setStatus(on and "Gravity override on" or "Gravity restored") end) makeSlider(playerPage, "Gravity", 10, 300, State.gravity, 0, function(v) State.gravity = v end) makeSection(playerPage, "Swimming") makeToggle(playerPage, "Swim Speed Override", false, function(on) State.swimSpeedEnabled = on setStatus(on and "Swim speed override on" or "Swim speed override off") end) makeSlider(playerPage, "Swim Speed", 16, 120, State.swimSpeed, 0, function(v) State.swimSpeed = v end) makeButton(playerPage, "Refill Swim Meter Now", false, function() local sc = findSwimController() if sc and sc._meterMax then sc._swimMeter = sc._meterMax cancelDrown(sc) if sc._swimming then LocalPlayer:SetAttribute("SwimMeter", 1) end setStatus("Swim meter refilled") else setStatus("SwimController not found") end end) makeSection(playerPage, "Survival") setAntiDeathToggle = makeToggle(playerPage, "Anti-Shark / Anti-Death", false, function(on) State.antiDeath = on local h = getHumanoid() if h then applyAntiDeath(h, on) end setStatus(on and "Anti-Death on — shark & drown kills blocked" or "Anti-Death off") end) setInfOxygenToggle = makeToggle(playerPage, "Infinite Oxygen / Never Drown", false, function(on) State.infOxygen = on if on then local sc = findSwimController() if sc then sc._infiniteSwim = true if sc._meterMax then sc._swimMeter = sc._meterMax end cancelDrown(sc) setStatus("Infinite Oxygen on — SwimController hooked") else setStatus("Infinite Oxygen on (controller pending — will hook when found)") end else local sc = findSwimController() if sc then sc._infiniteSwim = false end setStatus("Infinite Oxygen off") end end) makeToggle(playerPage, "Freeze Character", false, function(on) State.freeze = on setStatus(on and "Character frozen in place" or "Character unfrozen") end) makeSection(playerPage, "Flight (WASD + Space/Ctrl)") local setFlyToggle = makeToggle(playerPage, "Fly (F)", false, function(on) State.fly = on if on then startFly() else stopFly() end setStatus(on and "Fly on — WASD, Space up, Ctrl down" or "Fly off") end) makeSlider(playerPage, "Fly Speed", 20, 250, State.flySpeed, 0, function(v) State.flySpeed = v end) makeButton(playerPage, "Reset Character", true, function() local h = getHumanoid() if h then h.Health = 0 end setStatus("Respawning...") end) -- VISUALS ------------------------------------------------- makeSection(visualsPage, "ESP (highlight + distance)") makeToggle(visualsPage, "Chest ESP", false, function(on) State.espChests = on espGroups.Chest.enabled = on setStatus(on and "Chest ESP on" or "Chest ESP off") end) makeToggle(visualsPage, "Drain ESP", false, function(on) State.espDrains = on espGroups.Pour.enabled = on setStatus(on and "Drain ESP on" or "Drain ESP off") end) makeToggle(visualsPage, "Water ESP", false, function(on) State.espWater = on espGroups.Water.enabled = on setStatus(on and "Water ESP on" or "Water ESP off") end) makeToggle(visualsPage, "Player ESP", false, function(on) State.espPlayers = on setStatus(on and "Player ESP on" or "Player ESP off") end) makeSection(visualsPage, "Players") makeToggle(visualsPage, "Hide Other Players", false, function(on) State.hidePlayers = on setStatus(on and "Other players hidden (local only)" or "Other players visible") end) makeSection(visualsPage, "Camera") makeButton(visualsPage, "Unlock Third Person", false, function() LocalPlayer.CameraMode = Enum.CameraMode.Classic LocalPlayer.CameraMaxZoomDistance = 128 LocalPlayer.CameraMinZoomDistance = 0.5 setStatus("Third person unlocked — scroll to zoom out") end) makeButton(visualsPage, "Force First Person", false, function() LocalPlayer.CameraMode = Enum.CameraMode.LockFirstPerson setStatus("Back to first person") end) makeToggle(visualsPage, "FOV Override", false, function(on) State.fovEnabled = on if not on then local cam = Workspace.CurrentCamera if cam then cam.FieldOfView = 70 end end end) makeSlider(visualsPage, "Field Of View", 40, 120, State.fov, 0, function(v) State.fov = v end) makeButton(visualsPage, "Unlock Camera Zoom", false, function() LocalPlayer.CameraMaxZoomDistance = 4096 LocalPlayer.CameraMinZoomDistance = 0.5 setStatus("Camera zoom unlocked (0.5 – 4096 studs)") end) makeSection(visualsPage, "Lighting") makeSlider(visualsPage, "Time Of Day", 0, 24, Lighting.ClockTime, 1, function(v) Lighting.ClockTime = v end) makeButton(visualsPage, "Remove Fog & Effects", false, function() Lighting.FogEnd = 1e9 Lighting.FogStart = 1e9 for _, e in Lighting:GetChildren() do if e:IsA("BlurEffect") or e:IsA("DepthOfFieldEffect") or e:IsA("Atmosphere") then e:Destroy() end end setStatus("Fog, blur, DoF, and atmosphere removed") end) -- SKILLS -------------------------------------------------- makeSection(skillsPage, "Auto-Buy (server validates everything)") makeButton(skillsPage, "Buy All: Bucket Capacity", false, function() setStatus("Buying BUCKET_CAPACITY nodes...") autoBuySkills("BUCKET_CAPACITY", setStatus) end) makeButton(skillsPage, "Buy All: Fast Scoop", false, function() setStatus("Buying SCOOP_COOLDOWN nodes...") autoBuySkills("SCOOP_COOLDOWN", setStatus) end) makeButton(skillsPage, "Buy All: Token Earnings", false, function() setStatus("Buying TOKEN_EARNINGS_PCT nodes...") autoBuySkills("TOKEN_EARNINGS_PCT", setStatus) end) makeButton(skillsPage, "Buy All: Infinite Swim", false, function() setStatus("Buying INFINITE_SWIM nodes...") autoBuySkills("INFINITE_SWIM", setStatus) end) makeButton(skillsPage, "Buy Entire Skill Tree", false, function() setStatus("Buying every affordable node...") autoBuySkills(nil, setStatus) end) -- SERVER / MISC ------------------------------------------- makeSection(serverPage, "Utility") makeToggle(serverPage, "Anti-AFK", false, function(on) State.antiAfk = on setStatus(on and "Anti-AFK enabled" or "Anti-AFK disabled") end) makeToggle(serverPage, "Fullbright", false, function(on) State.fullbright = on setFullbright(on) setStatus(on and "Fullbright on" or "Fullbright off") end) makeSection(serverPage, "Waypoints") makeButton(serverPage, "Save Waypoint (here)", false, function() local root = getRoot() if root then savedWaypoint = root.CFrame setStatus(("Waypoint saved at (%d, %d, %d)"):format(root.Position.X, root.Position.Y, root.Position.Z)) end end) makeButton(serverPage, "Teleport To Waypoint", false, function() local root = getRoot() if root and savedWaypoint then root.AssemblyLinearVelocity = Vector3.zero root.CFrame = savedWaypoint setStatus("Teleported to waypoint") else setStatus("No waypoint saved yet") end end) makeButton(serverPage, "TP To Nearest Player", false, function() local root = getRoot() if not root then return end local best: Player? = nil local bestDist = math.huge for _, plr in Players:GetPlayers() do if plr ~= LocalPlayer and plr.Character then local pos = instancePosition(plr.Character) if pos then local d = (pos - root.Position).Magnitude if d < bestDist then bestDist = d best = plr end end end end if best and best.Character then local pos = instancePosition(best.Character) if pos then teleportTo(pos + Vector3.new(0, 3, 3)) setStatus("Teleported to " .. best.Name) end else setStatus("No other players in this server") end end) makeSection(serverPage, "Teleport / Rejoin") makeButton(serverPage, "Return To Lobby", false, function() fire("Revive.Lobby") fire("ReturnToLobby") setStatus("Requested return to lobby") end) makeButton(serverPage, "Rejoin Server", false, function() setStatus("Saving state and preparing the next server...") farmRejoinServer() end) makeButton(serverPage, "Copy Job ID", false, function() local ok = pcall(function() (setclipboard or (toclipboard :: any) or function() end)(game.JobId) end) setStatus(ok and ("JobId: " .. game.JobId) or "Clipboard not available") end) makeSection(serverPage, "Cmdr Console") makeButton(serverPage, "Open Cmdr (F2)", false, function() local ok, CmdrClient = pcall(function() return require(ReplicatedStorage:WaitForChild("CmdrClient", 3)) end) if ok and CmdrClient then pcall(function() CmdrClient:SetActivationKeys({ Enum.KeyCode.F2 }) if (CmdrClient :: any).Show then (CmdrClient :: any):Show() end end) setStatus("Cmdr ready — press F2 (needs CmdrAccess; off in live game)") else setStatus("CmdrClient not found") end end) -- SETTINGS ------------------------------------------------ makeSection(settingsPage, "GUI") local rebindBtn: TextButton local awaitingRebind = false rebindBtn = makeButton(settingsPage, "Toggle Key: LeftAlt (click to rebind)", false, function() awaitingRebind = true rebindBtn.Text = "Press any key..." setStatus("Press the key you want to toggle the GUI with") end) makeToggle(settingsPage, "Unlock Mouse While Open", true, function(on) State.unlockMouse = on setStatus(on and "Mouse auto-unlocks while GUI is open" or "Mouse unlock disabled") end) makeSection(settingsPage, "Hotkeys") do local info = Instance.new("TextLabel") info.Size = UDim2.new(1, 0, 0, 64) info.BackgroundColor3 = THEME.panel info.BorderSizePixel = 0 info.Font = Enum.Font.Gotham info.TextSize = 12 info.TextColor3 = THEME.textDim info.TextXAlignment = Enum.TextXAlignment.Left info.TextYAlignment = Enum.TextYAlignment.Top info.Text = " LeftAlt — open/close GUI\n F — toggle fly\n N — toggle noclip\n Space — infinite jump (when enabled)" info.Parent = settingsPage local ic = Instance.new("UICorner") ic.CornerRadius = UDim.new(0, 6) ic.Parent = info end makeSection(settingsPage, "Danger Zone") makeButton(settingsPage, "Destroy GUI", true, function() State.farm = false farmSaveState() State.autoScoop = false State.autoPour = false State.autoTokens = false State.autoChests = false State.speedEnabled = false State.jumpEnabled = false State.infiniteJump = false State.noclip = false State.fly = false State.freeze = false State.hidePlayers = false State.espPlayers = false State.swimSpeedEnabled = false stopFly() if State.gravityEnabled then State.gravityEnabled = false Workspace.Gravity = defaultGravity end if State.fullbright then setFullbright(false) end if State.antiDeath then State.antiDeath = false local h = getHumanoid() if h then applyAntiDeath(h, false) end end if State.infOxygen then State.infOxygen = false local sc = findSwimController() if sc then sc._infiniteSwim = false end end for _, group in espGroups do group.enabled = false clearEspGroup(group) end clearPlayerEsp() for _, plr in Players:GetPlayers() do if plr ~= LocalPlayer and plr.Character then setCharacterHidden(plr.Character, false) end end pcall(function() RunService:UnbindFromRenderStep("BucketHubMouseUnlock") end) espHolder:Destroy() environment.__BUCKET_HUB_RUNNING = nil gui:Destroy() end) selectTab("Farm") -- ========================================================= -- Live info + hotkeys -- ========================================================= local frameCount = 0 RunService.RenderStepped:Connect(function() frameCount += 1 end) task.spawn(function() local Stats = game:GetService("Stats") while gui.Parent do local fps = frameCount * 2 frameCount = 0 local ping = 0 pcall(function() ping = math.floor(Stats.Network.ServerStatsItem["Data Ping"]:GetValue()) end) fillLabel.Text = ("%d%% | %dfps | %dms"):format(math.floor(getBucketFill() * 100 + 0.5), fps, ping) task.wait(0.5) end end) UserInputService.InputBegan:Connect(function(input, processed) if input.UserInputType == Enum.UserInputType.Keyboard then heldKeys[input.KeyCode] = true -- rebind capture (works even when the click was processed by the GUI) if awaitingRebind and input.KeyCode ~= Enum.KeyCode.Unknown then awaitingRebind = false State.toggleKey = input.KeyCode rebindBtn.Text = ("Toggle Key: %s (click to rebind)"):format(input.KeyCode.Name) setStatus(("GUI toggle key set to %s"):format(input.KeyCode.Name)) return end end -- The toggle key must work even when `processed` is true — in first -- person the game/GUI often sinks input, and Alt is a modifier key. if input.KeyCode == State.toggleKey then setGuiOpen(not main.Visible) return end if processed then return end if input.KeyCode == Enum.KeyCode.F then setFlyToggle(not State.fly) elseif input.KeyCode == Enum.KeyCode.N then setNoclipToggle(not State.noclip) elseif input.KeyCode == Enum.KeyCode.Space and State.infiniteJump then local humanoid = getHumanoid() if humanoid then humanoid:ChangeState(Enum.HumanoidStateType.Jumping) end end end) UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.Keyboard then heldKeys[input.KeyCode] = false end end) -- Re-apply persistent features on respawn LocalPlayer.CharacterAdded:Connect(function(char) table.clear(heldKeys) if State.antiDeath then local humanoid = char:WaitForChild("Humanoid", 5) if humanoid and humanoid:IsA("Humanoid") then applyAntiDeath(humanoid, true) end end if State.infOxygen then -- the SwimController resets its state on respawn; re-hook it task.wait(0.5) local sc = findSwimController() if sc then sc._infiniteSwim = true end end if State.fly then task.wait(0.4) startFly() end end) -- ========================================================= -- Farm auto-resume (after a rejoin, when auto-executed) -- ========================================================= task.spawn(function() if not State.farmAutoResume then return end if savedFarmWasRunning and not State.farm then farmLog("Previous run found — resuming in 5 seconds") task.wait(5) if not State.farm then setFarmToggle(true) end end end) local loaderReady = farmGetLoader() ~= nil setStatus(loaderReady and "Ready — rejoin reload is armed" or "Ready — save as buckethub-v4.lua or set BUCKET_HUB_URL for rejoin reload")