
Cash Generator - Fast, Undetected.
by Bloxive ImportsAbout this script
HOW TO USE: Just execute it inside of Blox Fruits and it will start. - Collects Chests at fastest rate possible - NO LAG - Variable Speed (Lower it if you experience rubber banding probably wont tho) - No overhead (Option to not load UI at all at top of script in variables. - ~5,000 $/min in FIRST sea. Second and Third should be significantly more. ANTI-AFK now included.
Script code
Lua-- Scriptblox Analytics
pcall(function() loadstring(game:HttpGet("https://scriptblox.com/ingest/clientv2.lua"))("proj_90a9005b5684", "1.0.0", false) end)
-- Dynamic CanTouch farmer with a discovery pass and persistent streaming memory.
local SPEED = 190 -- Fallback horizontal speed on foot in studs per second.
local SPEED_MIN = 250 -- Minimum sinusoidal speed in studs per second.
local SPEED_MAX = 259.9 -- Maximum sinusoidal speed in studs per second.
local SPEED_PERIOD = 0.2 -- Complete sinusoidal cycle period in seconds (5 Hz).
local EFFECTIVE_AVG_SPEED = (SPEED_MAX + SPEED_MIN) * 0.5 -- 254.95 studs/s nominal average
local BOAT_PURCHASE_RANGE = 450
local BOAT_APPROACH_RANGE = 420 -- Margin for dealer position offsets.
local MIN_ROOT_Y = 2.0 -- Strict altitude floor (keeps boat above waterline at all times).
local MAX_TRAVEL_SECONDS = 180
local LOAD_UI = true
local SHOW_ROUTE_TRACERS = true
local SHOW_HITBOX_VISUALIZER = true -- Gold outlines for chest targets, including the discovery pass.
local REWARD_SEA = 1 -- Set to 1, 2, or 3 for your current Sea.
local ESTIMATED_PICKUP_SECONDS = 0.03
local LOOKAHEAD_STOPS = 4
local MAP_OUTLIER_DISTANCE = 10000 -- Ignore very distant spawns when fitting the chest map.
local DISCOVERY_RUN = true -- Discover through known chest locations once; dealers are only for getting a boat.
local DISCOVERY_RADIUS = 200 -- Nearby discovery seeds share one streaming stop.
local STREAM_TIMEOUT = 2 -- Bound each streaming request; no parallel request flood.
-- Chest trigger geometry
local HITBOX_SIZE = Vector3.new(100, 100, 100)
local HITBOX_HALF_EXTENT = 50 -- Start at the face of the 100x100x100 trigger, with no 5-stud inset.
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
while not player do
task.wait()
player = Players.LocalPlayer
end
print("[Chest Farmer] Script started")
-- Sinusoidal 3D Speed Generator (250 - 259.9 studs/s) Synchronized with Server Clock
local function getSinusoidalSpeed(serverTime)
local mid = (SPEED_MAX + SPEED_MIN) * 0.5 -- 254.95
local amp = (SPEED_MAX - SPEED_MIN) * 0.5 -- 4.95
local omega = (2 * math.pi) / SPEED_PERIOD
local serverTimeCycle = serverTime % SPEED_PERIOD
return mid + amp * math.sin(serverTimeCycle * omega)
end
local C = {
Speed = SPEED,
BoatSpeed = EFFECTIVE_AVG_SPEED,
MinRootY = MIN_ROOT_Y,
PollSeconds = 0.05,
SweepMargin = 5, -- Continue a short distance past the hitbox face for touch registration.
MinimumTouchDepth = 4,
ArrivalDistance = 4,
PendingConfirmSeconds = 3,
CharacterTimeout = 15,
ChestFailureCooldown = 10,
MaxChestCooldown = 120,
MatchRadius = 1,
ObserveSeconds = 0.5, -- Fallback polling; CanTouch changes also update state immediately.
ReplanSeconds = 1,
SwitchGain = 1.25,
MinimumCommitSeconds = 1.5,
FinishDistance = 30,
BeamWidth = 8,
BranchWidth = 8,
PlanBudgetSeconds = 0.0015,
MapRefreshSeconds = 0.5,
Debug = true,
}
-- Loaded CanTouch is authoritative. Timers predict only known, unloaded chests.
local gradeBySpawnName = {Chest1 = "Silver", Chest2 = "Gold", Chest3 = "Diamond"}
local chestEconomy = {
Silver = {respawn = 180, rewards = {{250, 420}, {500, 1000}, {1000, 1695}}},
Gold = {respawn = 360, rewards = {{600, 1100}, {2300, 3120}, {3875, 5200}}},
Diamond = {respawn = 720, rewards = {{1500, 3000}, {5000, 7250}, {8000, 12250}}},
}
local function gradeOf(record) return gradeBySpawnName[record.name] or "Gold" end
local function economyOf(record) return chestEconomy[gradeOf(record)] end
local function respawnOf(record) return record.respawnEstimate or (gradeBySpawnName[record.name] and economyOf(record).respawn) end
local function enforceAltitudeFloor(position)
if position.Y >= C.MinRootY then return position end
return Vector3.new(position.X, C.MinRootY, position.Z)
end
-- CALCULATED LEG SPEED TRACKER
local legHistory = {}
local maxLegHistory = 15
local avgLegSpeed = 0
local legHistoryMode = nil
local measuredMotion = {}
local function recordLegPerformance(distance, timeTaken, mode)
if timeTaken <= 0.02 or distance <= 4.0 then return end
if legHistoryMode ~= mode then
table.clear(legHistory)
legHistoryMode = mode
end
table.insert(legHistory, {distance = distance, time = timeTaken})
if #legHistory > maxLegHistory then
table.remove(legHistory, 1)
end
local totalDistance, totalTime = 0, 0
for _, leg in ipairs(legHistory) do
totalDistance += leg.distance
totalTime += leg.time
end
avgLegSpeed = totalDistance / totalTime
measuredMotion[mode] = {speed = avgLegSpeed, samples = #legHistory}
end
-- ROUTE PLANNER (Direct 3D Euclidean Distance)
local Planner = {}
function Planner.travelSeconds(a, b, speed3D)
local dist3D = (b - a).Magnitude
local mode = speed3D == C.Speed and "foot" or "boat"
local observed = measuredMotion[mode]
local calibrated = speed3D
if observed and observed.samples >= 3 then
calibrated = math.clamp(observed.speed, speed3D * 0.7, speed3D * 1.1)
end
return dist3D / calibrated
end
function Planner.sweepPath(node, fromPosition, margin)
local center = enforceAltitudeFloor(node.position)
local half = node.halfSize or Vector3.new(HITBOX_HALF_EXTENT, HITBOX_HALF_EXTENT, HITBOX_HALF_EXTENT)
-- Coordinate clamping gives the nearest point on the shared trigger box,
-- rather than intersecting a longer ray aimed at the chest's center.
local entryPoint = Vector3.new(
math.clamp(fromPosition.X, center.X - half.X, center.X + half.X),
math.clamp(fromPosition.Y, center.Y - half.Y, center.Y + half.Y),
math.clamp(fromPosition.Z, center.Z - half.Z, center.Z + half.Z))
local inward = center - entryPoint
local direction = inward.Magnitude > 0.001 and inward.Unit or Vector3.new(0, 0, -1)
local exitPoint = entryPoint + direction * (margin + 6)
-- Include the arrival tolerance so stopping short still leaves four studs inside.
-- Thin shared regions use their center, the deepest point common to all members.
local depth = C.MinimumTouchDepth + C.ArrivalDistance
local inset = Vector3.new(math.min(depth, half.X), math.min(depth, half.Y), math.min(depth, half.Z))
exitPoint = Vector3.new(
math.clamp(exitPoint.X, center.X - half.X + inset.X, center.X + half.X - inset.X),
math.clamp(exitPoint.Y, center.Y - half.Y + inset.Y, center.Y + half.Y - inset.Y),
math.clamp(exitPoint.Z, center.Z - half.Z + inset.Z, center.Z + half.Z - inset.Z))
return enforceAltitudeFloor(entryPoint), center, enforceAltitudeFloor(exitPoint)
end
function Planner.leg(position, node, startAt, now, options)
local entry, _, exit = Planner.sweepPath(node, position, options.sweepMargin)
local travel = options.travelEstimator and options.travelEstimator(position, entry)
or Planner.travelSeconds(position, entry, options.speed)
if travel > options.maxTravel then return nil end
if node.readyAt and node.readyAt > startAt + travel then return nil end
local sweepSeconds = options.travelEstimator(entry, exit)
return {seconds = math.max(0.01, travel + sweepSeconds + options.service),
probability = node.reliability, exitPosition = exit}
end
local function better(a, b)
if math.abs(a.score - b.score) > 1e-9 then return a.score > b.score end
if math.abs(a.elapsed - b.elapsed) > 1e-9 then return a.elapsed < b.elapsed end
return a.first.id < b.first.id
end
local function keepBest(list, entry, limit)
local index = #list + 1
for i, old in ipairs(list) do if better(entry, old) then index = i; break end end
if index <= limit then
table.insert(list, index, entry)
if #list > limit then table.remove(list) end
end
end
function Planner.plan(position, nodes, now, options, forcedFirstId)
local beam = {{position = position, elapsed = 0, reward = 0, visited = {}, route = {}}}
local best
local deadline = options.budget and (os.clock() + options.budget)
-- Examine every first stop once, then bound deeper expansion by the CPU budget.
local roots = {}
for _, node in ipairs(nodes) do
if not forcedFirstId or node.id == forcedFirstId then
local leg = Planner.leg(position, node, now, now, options)
if leg then
local reward = node.value * leg.probability
keepBest(roots, {position = leg.exitPosition, first = node, elapsed = leg.seconds,
reward = reward, score = reward / (leg.seconds + options.smoothing),
visited = {[node.id] = true}, route = {node}}, options.width)
end
end
end
if #roots == 0 then return nil end
beam, best = roots, roots[1]
for depth = 2, options.depth do
local expanded = {}
for _, state in ipairs(beam) do
if depth > 1 and deadline and os.clock() >= deadline then return best end
local branches = {}
local exhausted = false
for nodeIndex, node in ipairs(nodes) do
if not state.visited[node.id] and (depth > 1 or not forcedFirstId or node.id == forcedFirstId) then
local leg = Planner.leg(state.position, node, now + state.elapsed, now, options)
if leg then
local elapsed = state.elapsed + leg.seconds
local reward = state.reward + node.value * leg.probability
local entry = {
position = leg.exitPosition, first = state.first or node,
elapsed = elapsed, reward = reward,
score = reward / (elapsed + options.smoothing),
parent = state, node = node,
}
keepBest(branches, entry, options.branch)
end
end
if nodeIndex % 16 == 0 and deadline and os.clock() >= deadline then
exhausted = true
break
end
end
for _, entry in ipairs(branches) do
entry.visited = table.clone(entry.parent.visited)
entry.visited[entry.node.id] = true
entry.route = table.clone(entry.parent.route)
table.insert(entry.route, entry.node)
entry.parent, entry.node = nil, nil
keepBest(expanded, entry, options.width)
if not best or better(entry, best) then best = entry end
end
if exhausted then return best end
end
if #expanded == 0 then break end
beam = expanded
end
return best
end
-- DEALER & BOAT CORE
local dealerList, lastDealerScan = {}, -math.huge
local ownedBoat = nil
local function rememberDealer(npc)
if not (npc:IsA("Model") or npc:IsA("BasePart"))
or not npc.Name:lower():gsub("%s+", ""):find("boatdealer", 1, true) then return end
local folder = workspace:FindFirstChild("NPCs")
if not folder or not npc:IsDescendantOf(folder) then return end
local position = npc:IsA("Model") and npc:GetPivot().Position or npc.Position
for _, dealer in ipairs(dealerList) do
if (dealer.position - position).Magnitude <= 5 then
dealer.instance, dealer.position, dealer.name = npc, position, npc.Name
return
end
end
table.insert(dealerList, {instance = npc, position = position, name = npc.Name})
end
local function scanDealers(force)
local now = workspace:GetServerTimeNow()
if not force and now - lastDealerScan < 3 then return end
lastDealerScan = now
for i = #dealerList, 1, -1 do
local dealer = dealerList[i]
if dealer.instance and not dealer.instance:IsDescendantOf(workspace) then
dealer.instance = nil
end
end
end
local function boatSeat(boat)
if not boat or not boat.Parent then return nil end
local seat = boat:FindFirstChild("VehicleSeat", true)
return seat and seat:IsA("VehicleSeat") and seat or nil
end
local function boatBelongsToPlayer(boat)
local seat = boatSeat(boat)
if seat and seat.Occupant and seat.Occupant.Parent == player.Character then return true end
local owner = boat:FindFirstChild("Owner", true)
if not owner or not owner:IsA("ValueBase") then return false end
local value = owner.Value
return value == player or value == player.Name or value == player.UserId
or tostring(value) == tostring(player.UserId)
end
-- CHARACTER & VELOCITY HELPERS
local function parts()
local char = player.Character
local root = char and char:FindFirstChild("HumanoidRootPart")
local hum = char and char:FindFirstChildOfClass("Humanoid")
if char and char:IsDescendantOf(workspace) and root and hum and hum.Health > 0 then
return char, root, hum
end
end
local function getLiveVelocity()
local char, root, hum = parts()
if not char or not root then return 0 end
if hum and hum.SeatPart and hum.SeatPart:IsA("VehicleSeat") then
local motionPart = hum.SeatPart.AssemblyRootPart or hum.SeatPart
local vel = motionPart.AssemblyLinearVelocity or motionPart.Velocity
return vel.Magnitude
else
local vel = root.AssemblyLinearVelocity or root.Velocity
return vel.Magnitude
end
end
-- UI CREATION
local playerGui = player:FindFirstChildOfClass("PlayerGui")
local GUI_NAME = "ChestFarmerBoat"
local globalEnvironment = getgenv and getgenv() or _G
if globalEnvironment.ChestFarmerBoatStop then pcall(globalEnvironment.ChestFarmerBoatStop) end
local oldGui = playerGui and playerGui:FindFirstChild(GUI_NAME)
if oldGui then oldGui:Destroy() end
local gui = Instance.new("ScreenGui")
gui.Name, gui.ResetOnSpawn = GUI_NAME, false
if LOAD_UI then
if playerGui then
gui.Parent = playerGui
else
task.spawn(function()
local latePlayerGui = player:WaitForChild("PlayerGui")
if not gui.Parent then gui.Parent = latePlayerGui end
end)
end
end
local panel = Instance.new("Frame")
panel.Size = UDim2.fromOffset(300, 224)
panel.Position = UDim2.fromOffset(15, 100)
panel.BackgroundColor3 = Color3.fromRGB(25, 28, 34)
panel.BorderSizePixel = 0
panel.Parent = gui
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 10)
corner.Parent = panel
local panelScale = Instance.new("UIScale")
panelScale.Parent = panel
local function label(text, x, y, width, height, size, color)
local item = Instance.new("TextLabel")
item.BackgroundTransparency = 1
item.Position = UDim2.fromOffset(x, y)
item.Size = UDim2.fromOffset(width, height)
item.Font = Enum.Font.Gotham
item.TextSize = size
item.TextColor3 = color
item.TextXAlignment = Enum.TextXAlignment.Left
item.TextTruncate = Enum.TextTruncate.AtEnd
item.Text = text
item.Parent = panel
return item
end
local light = Color3.fromRGB(240, 242, 245)
local muted = Color3.fromRGB(160, 167, 178)
local titleLabel = label("Chest Farm · Initializing", 14, 10, 150, 26, 16, light)
label("Money gained", 14, 46, 130, 18, 11, muted)
label("Money / min", 157, 46, 130, 18, 11, muted)
local gainedLabel = label("—", 14, 65, 130, 24, 18, Color3.fromRGB(125, 225, 163))
local rateLabel = label("—", 157, 65, 130, 24, 18, light)
label("Live velocity", 14, 95, 130, 18, 11, muted)
label("Avg leg speed", 157, 95, 130, 18, 11, muted)
local speedLabel = label("0.0 studs/s", 14, 114, 130, 22, 14, Color3.fromRGB(80, 200, 255))
local avgSpeedLabel = label("—", 157, 114, 130, 22, 14, Color3.fromRGB(125, 225, 163))
local nextPassLabel = label("Watching for active chests…", 14, 142, 272, 17, 11, light)
local availabilityLabel = label("Finding chests…", 14, 160, 272, 17, 11, muted)
local plannerLabel = label("Live planner starting…", 14, 178, 272, 17, 10, muted)
local statusLabel = label("Starting…", 14, 198, 272, 17, 11, muted)
local updateSmallDetails
local stopButton = Instance.new("TextButton")
stopButton.Size = UDim2.fromOffset(60, 26)
stopButton.Position = UDim2.fromOffset(226, 10)
stopButton.Text = "Stop"
stopButton.Font = Enum.Font.Gotham
stopButton.TextSize = 12
stopButton.TextColor3 = light
stopButton.BackgroundColor3 = Color3.fromRGB(55, 60, 70)
stopButton.BorderSizePixel = 0
stopButton.Parent = panel
local buttonCorner = Instance.new("UICorner")
buttonCorner.CornerRadius = UDim.new(0, 6)
buttonCorner.Parent = stopButton
local mapButton = Instance.new("TextButton")
mapButton.Size = UDim2.fromOffset(54, 26)
mapButton.Position = UDim2.fromOffset(166, 10)
mapButton.Text = "Map"
mapButton.Font = Enum.Font.Gotham
mapButton.TextSize = 12
mapButton.TextColor3 = light
mapButton.BackgroundColor3 = Color3.fromRGB(55, 60, 70)
mapButton.BorderSizePixel = 0
mapButton.Parent = panel
local mapButtonCorner = Instance.new("UICorner")
mapButtonCorner.CornerRadius = UDim.new(0, 6)
mapButtonCorner.Parent = mapButton
local stopped = false
local connections = {}
local uiInput = game:GetService("UserInputService")
local uiLastViewport = Vector2.zero
local uiLastTouch = nil
local uiPanelPosition
local function positionStats(position)
local camera = workspace.CurrentCamera
if not camera then return end
local topLeft, bottomRight = game:GetService("GuiService"):GetGuiInset()
local usable = camera.ViewportSize - topLeft - bottomRight
local size = Vector2.new(panel.Size.X.Offset, panel.Size.Y.Offset) * panelScale.Scale
uiPanelPosition = Vector2.new(
math.clamp(position.X, 0, math.max(0, usable.X - size.X)),
math.clamp(position.Y, 0, math.max(0, usable.Y - size.Y)))
panel.Position = UDim2.fromOffset(uiPanelPosition.X, uiPanelPosition.Y)
end
local function layoutStats()
local camera = workspace.CurrentCamera
if not camera then return end
local viewport = camera.ViewportSize
local touch = uiInput.TouchEnabled
if viewport == uiLastViewport and touch == uiLastTouch then return end
uiLastViewport, uiLastTouch = viewport, touch
local topLeft, bottomRight = game:GetService("GuiService"):GetGuiInset()
local usable = viewport - topLeft - bottomRight
panelScale.Scale = math.min(1, math.max(0.5, (usable.X - 16) / 300))
panel.Size = UDim2.fromOffset(300, touch and 240 or 224)
positionStats(uiPanelPosition or Vector2.new(touch and 8 or 15, touch and 8 or math.min(100, math.max(8, usable.Y - 232))))
stopButton.Size = UDim2.fromOffset(60, touch and 42 or 26)
mapButton.Size = UDim2.fromOffset(54, touch and 42 or 26)
stopButton.Position = UDim2.fromOffset(226, touch and 4 or 10)
mapButton.Position = UDim2.fromOffset(166, touch and 4 or 10)
for _, child in ipairs(panel:GetChildren()) do
if child:IsA("TextLabel") then
local originalY = child:GetAttribute("LayoutY")
if not originalY then originalY = child.Position.Y.Offset; child:SetAttribute("LayoutY", originalY) end
child.Position = UDim2.fromOffset(child.Position.X.Offset, originalY + (touch and originalY >= 46 and 16 or 0))
end
end
end
layoutStats()
-- Drag from the title area; Map and Stop remain independent tap targets.
local dragHandle = Instance.new("Frame")
dragHandle.Name = "DragHandle"
dragHandle.BackgroundTransparency = 1
dragHandle.Size = UDim2.fromOffset(158, 44)
dragHandle.Active = true
dragHandle.ZIndex = 5
dragHandle.Parent = panel
local statsDragInput, statsDragStart, statsDragPosition
table.insert(connections, dragHandle.InputBegan:Connect(function(input)
if stopped or statsDragInput then return end
if input.UserInputType ~= Enum.UserInputType.MouseButton1
and input.UserInputType ~= Enum.UserInputType.Touch then return end
statsDragInput = input
statsDragStart = Vector2.new(input.Position.X, input.Position.Y)
statsDragPosition = Vector2.new(panel.Position.X.Offset, panel.Position.Y.Offset)
end))
table.insert(connections, uiInput.InputChanged:Connect(function(input)
if not statsDragInput or stopped or not panel.Visible then return end
if input == statsDragInput or (statsDragInput.UserInputType == Enum.UserInputType.MouseButton1
and input.UserInputType == Enum.UserInputType.MouseMovement) then
local position = Vector2.new(input.Position.X, input.Position.Y)
positionStats(statsDragPosition + position - statsDragStart)
end
end))
table.insert(connections, uiInput.InputEnded:Connect(function(input)
if input == statsDragInput then statsDragInput = nil end
end))
local virtualUser = game:GetService("VirtualUser")
local antiAfkConnection = player.Idled:Connect(function()
virtualUser:CaptureController()
virtualUser:ClickButton2(Vector2.new())
end)
table.insert(connections, antiAfkConnection)
local candidates, records = {}, {}
local chestOriginals = setmetatable({}, {__mode = "k"})
local currentRouteDestination
local currentTargetBoxCenter = nil
local currentTargetRecords = nil
local currentNextRoutePosition = nil
local choose, eligible, observeRecord
local liveNavigation = {plan = nil, nodeCount = 0, planMilliseconds = 0, speed = C.BoatSpeed}
local discovery = {active = DISCOVERY_RUN, regions = {}, completed = 0, skipped = 0,
seededRecords = {}, lastSeedScan = -math.huge}
local streamingJob
local function requestStream(position)
if not workspace.StreamingEnabled or stopped then return nil end
if streamingJob and not streamingJob.done then
return (streamingJob.position - position).Magnitude <= DISCOVERY_RADIUS and streamingJob or nil
end
local job = {position = position, done = false}
streamingJob = job
task.spawn(function()
job.ok = pcall(function() player:RequestStreamAroundAsync(position, STREAM_TIMEOUT) end)
job.done = true
end)
return job
end
local lastObserved = -math.huge
local function log(message)
if C.Debug then print("[Chest Farmer] " .. message) end
end
local function display(message)
if gui.Parent then statusLabel.Text = message end
end
local startingBeli, moneyStarted
local function formatMoney(value)
local rounded = math.floor(math.abs(value) + 0.5)
local digits = string.format("%.0f", rounded)
local grouped = digits:reverse():gsub("(%d%d%d)", "%1,"):reverse():gsub("^,", "")
return (value < 0 and rounded > 0 and "-$" or "$") .. grouped
end
local function readBeli()
local data = player:FindFirstChild("Data")
local value = data and data:FindFirstChild("Beli")
if value and (value:IsA("IntValue") or value:IsA("NumberValue")) then return value.Value end
end
local function updateMoney()
if not gui.Parent then return end
local balance = readBeli()
if not balance then return end
local now = workspace:GetServerTimeNow()
if startingBeli == nil then startingBeli, moneyStarted = balance, now end
local gained = balance - startingBeli
local elapsed = now - moneyStarted
gainedLabel.Text = formatMoney(gained)
rateLabel.Text = formatMoney(elapsed > 0 and gained * 60 / elapsed or 0)
end
local moneyRefreshAt = 0
table.insert(connections, RunService.Heartbeat:Connect(function()
if not gui.Parent then return end
layoutStats()
local velocityText = string.format("%.1f studs/s", getLiveVelocity())
if speedLabel.Text ~= velocityText then speedLabel.Text = velocityText end
local now = os.clock()
if now < moneyRefreshAt then return end
moneyRefreshAt = now + 0.25
updateMoney()
if updateSmallDetails then updateSmallDetails() end
if avgLegSpeed > 0 then
avgSpeedLabel.Text = string.format("%.1f studs/s", avgLegSpeed)
else
avgSpeedLabel.Text = "—"
end
end))
local function stop()
if stopped then return end
stopped = true
display("Stopping farm…")
end
globalEnvironment.ChestFarmerBoatStop = stop
table.insert(connections, stopButton.Activated:Connect(stop))
table.insert(connections, gui.Destroying:Connect(stop))
local function waitCharacter(timeout)
local deadline = workspace:GetServerTimeNow() + timeout
repeat
local char, root, hum = parts()
if char then return char, root, hum end
task.wait(C.PollSeconds)
until stopped or workspace:GetServerTimeNow() >= deadline
end
local function available(part)
return part and part:IsDescendantOf(workspace) and part.CanTouch == true
end
local function loadedTrigger(record)
local trigger = record.spawnPart or record.part
return trigger and trigger:IsDescendantOf(workspace) and trigger or nil
end
local function rememberedReadyAt(record, now)
local trigger = loadedTrigger(record)
if trigger then return trigger.CanTouch and now or math.huge end
if not record.geometry or record.lastCanTouch == nil then return math.huge end
if record.lastCanTouch then return now end
return record.readyAt or math.huge
end
local function chestStatus(record, now)
local trigger = loadedTrigger(record)
if trigger and trigger.CanTouch then return "ready" end
if not trigger and rememberedReadyAt(record, now) <= now then return "remembered" end
if record.readyAt and record.readyAt < math.huge and record.readyAt > now then return "predicted" end
return record.lastCanTouch == nil and "unknown" or "empty"
end
local function enforceChestHitbox(part)
if stopped or not part:IsDescendantOf(workspace) then return end
pcall(function()
if part.Size ~= HITBOX_SIZE then part.Size = HITBOX_SIZE end
if part.CanCollide then part.CanCollide = false end
end)
end
local function track(obj)
rememberDealer(obj)
if not obj:IsA("BasePart") or not obj.Name:lower():find("chest", 1, true) then return end
local visualFolder = workspace:FindFirstChild("ChestModels")
if visualFolder and obj:IsDescendantOf(visualFolder) then return end
if not chestOriginals[obj] then
chestOriginals[obj] = {size = obj.Size, canCollide = obj.CanCollide}
for _, property in ipairs({"Size", "CanCollide"}) do
table.insert(connections, obj:GetPropertyChangedSignal(property):Connect(function()
enforceChestHitbox(obj)
end))
end
table.insert(connections, obj:GetPropertyChangedSignal("CanTouch"):Connect(function()
if stopped or not obj:IsDescendantOf(workspace) then return end
local record = candidates[obj]
if type(record) ~= "table" then return end
local attempt = record.pendingAttempt
if not obj.CanTouch and attempt and not attempt.done and attempt.activeBefore and attempt.crossed
and attempt.touchPart == obj then
attempt.deactivatedAt = workspace:GetServerTimeNow()
end
if observeRecord then observeRecord(record, obj, workspace:GetServerTimeNow()) end
end))
end
enforceChestHitbox(obj)
if candidates[obj] == nil then candidates[obj] = true end
end
table.insert(connections, workspace.DescendantAdded:Connect(track))
local initialScanComplete = false
task.spawn(function()
local pending = {workspace}
while not stopped and #pending > 0 do
for _ = 1, 200 do
local item = table.remove(pending)
if not item then break end
track(item)
for _, child in ipairs(item:GetChildren()) do table.insert(pending, child) end
end
task.wait()
end
initialScanComplete = not stopped
end)
-- REWARDS & COOLDOWNS (Server-Synchronized)
local function markEmpty(record, now, ours)
if record.state == "empty" and record.emptyAt and now - record.emptyAt < 5 then
if ours and record.lastLossCounted then
record.otherLosses = math.max(0, (record.otherLosses or 0) - 1)
record.lastLossCounted = false
end
return
end
record.emptyAt = now
record.readyAt = now + (respawnOf(record) or economyOf(record).respawn)
record.observationGap = false
record.state = "empty"
record.lastLossCounted = not ours
if not ours then record.otherLosses = (record.otherLosses or 0) + 1 end
end
observeRecord = function(record, trigger, now)
if not trigger or not trigger:IsDescendantOf(workspace) then
record.loaded, record.observationGap = false, true
return
end
local priorTouch = record.lastCanTouch
local gap = record.observationGap
record.spawnPart = trigger
record.loaded = true
if not record.geometry or record.geometry.cframe ~= trigger.CFrame or record.geometry.size ~= trigger.Size then
record.geometry = {cframe = trigger.CFrame, size = trigger.Size}
end
record.position, record.lastObservedAt = trigger.Position, now
if trigger.CanTouch then
if priorTouch == false and record.emptyAt and not gap then
local measured = now - record.emptyAt
local nominal = economyOf(record).respawn
if measured > nominal * 0.5 and measured < nominal * 1.5 then
record.respawnEstimate = (record.respawnEstimate or nominal) * 0.8 + measured * 0.2
end
end
record.part, record.state, record.collected = trigger, "ready", false
record.emptyAt, record.readyAt = nil, now
record.initiallyEmptyAt = nil
else
record.part = nil
if priorTouch == true then
local attempt = record.pendingAttempt
markEmpty(record, now, attempt and attempt.deactivatedAt ~= nil)
end
record.state = "empty"
if not record.emptyAt and not record.initiallyEmptyAt then
-- Unknown startup collection time: a full respawn interval is a conservative bound.
record.initiallyEmptyAt = now
record.readyAt = now + (respawnOf(record) or economyOf(record).respawn)
end
end
record.lastCanTouch, record.observationGap = trigger.CanTouch, false
end
local pendingAttempts = {}
local startupMissReports = 0
local lastPickupBalance = readBeli()
local function beginPending(record, sweepSeconds)
if record.pendingAttempt then return record.pendingAttempt end
local now = workspace:GetServerTimeNow()
local trigger = record.spawnPart or record.part
if not available(trigger) then return nil end
local attempt = {record = record, touchPart = trigger, activeBefore = available(trigger) == true,
expires = now + sweepSeconds + C.PendingConfirmSeconds + 1, crossed = false}
record.pendingAttempt = attempt
record.pendingUntil = attempt.expires
table.insert(pendingAttempts, attempt)
return attempt
end
local function confirmPickup(attempt, now)
if attempt.done then return end
attempt.done = true
local record = attempt.record
markEmpty(record, now, true)
record.collected = true
record.successes = (record.successes or 0) + 1
record.failures = 0
record.cooldown = now + 1
end
table.insert(connections, RunService.Heartbeat:Connect(function()
local now, balance = workspace:GetServerTimeNow(), readBeli()
if balance and lastPickupBalance and balance > lastPickupBalance then
local gain = balance - lastPickupBalance
-- Beli can combine several pickups or come from another source.
-- Retain it as supporting evidence; it cannot identify a chest by itself.
for _, attempt in ipairs(pendingAttempts) do
if not attempt.done and attempt.crossed and now <= attempt.expires then
attempt.beliEvidence = (attempt.beliEvidence or 0) + gain
end
end
end
if balance then lastPickupBalance = balance end
for i = #pendingAttempts, 1, -1 do
local attempt = pendingAttempts[i]
-- A pass alone is not a pickup: require contact, deactivation and reward evidence.
local observedPart = attempt.touchPart
if not attempt.done and attempt.crossed and attempt.activeBefore and now <= attempt.expires
and (attempt.beliEvidence or 0) > 0
and (attempt.deactivatedAt or (observedPart and observedPart:IsDescendantOf(workspace) and observedPart.CanTouch == false)) then
confirmPickup(attempt, attempt.deactivatedAt or now)
end
if attempt.done or now >= attempt.expires then
local record = attempt.record
if record.pendingAttempt == attempt then
record.pendingAttempt, record.pendingUntil = nil, nil
if not attempt.done and attempt.crossed and attempt.activeBefore
and observedPart and observedPart:IsDescendantOf(workspace) and observedPart.CanTouch then
if startupMissReports < 5 then
startupMissReports += 1
local char, root, hum = parts()
local touchParts, anchoredParts = 0, 0
if char then
for _, part in ipairs(char:GetDescendants()) do
if part:IsA("BasePart") then
if part.CanTouch then touchParts += 1 end
if part.Anchored then anchoredParts += 1 end
end
end
end
local trigger = record.part or record.spawnPart
log(string.format("Miss %d: %s | active trigger=%s | trigger CanTouch=%s | character touch parts=%d | anchored parts=%d | seated=%s | scan complete=%s",
startupMissReports, record.name, tostring(available(trigger) == true),
tostring(trigger and trigger.CanTouch), touchParts, anchoredParts,
tostring(hum and hum.SeatPart ~= nil), tostring(initialScanComplete)))
end
record.misses = (record.misses or 0) + 1
record.failures = (record.failures or 0) + 1
record.cooldown = now + math.min(C.MaxChestCooldown, C.ChestFailureCooldown * 2 ^ math.min(record.failures - 1, 4))
end
end
table.remove(pendingAttempts, i)
end
end
end))
local function refreshChests(force)
local now = workspace:GetServerTimeNow()
if not force and now - lastObserved < C.ObserveSeconds then return end
local observedSeconds = math.min(2, math.max(0, now - lastObserved))
lastObserved = now
for _, r in ipairs(records) do r.spawnPart = nil; r.part = nil end
for part in pairs(candidates) do
if not part:IsDescendantOf(workspace) then
candidates[part] = nil
else
enforceChestHitbox(part)
local r = candidates[part]
if r == true then
r = nil
for _, existing in ipairs(records) do
if existing.name == part.Name and (existing.position - part.Position).Magnitude <= C.MatchRadius then
r = existing
break
end
end
if not r then
r = {id = #records + 1, name = part.Name, position = part.Position,
cooldown = 0, failures = 0, successes = 0, misses = 0,
exposure = 0, otherLosses = 0, state = "unknown",
readyAt = math.huge}
table.insert(records, r)
end
candidates[part] = r
end
r.spawnPart = part
if available(part) then r.part = part end
r.position = part.Position
end
end
for _, r in ipairs(records) do
if r.state == "ready" then r.exposure = (r.exposure or 0) + observedSeconds end
observeRecord(r, r.spawnPart, now)
end
end
-- FALLBACK WALKING MOVEMENT (Only used when acquiring initial boat)
local function approachPosition(target, stopRadius)
local char, root, hum = parts()
if not char then return false end
target = enforceAltitudeFloor(target)
local previousFlight = root:FindFirstChild("ContinuousFlightVelocity")
local flightWasEnabled = previousFlight and previousFlight.Enabled
if previousFlight then previousFlight.Enabled = false end
local attachment = Instance.new("Attachment", root)
local drive = Instance.new("LinearVelocity", root)
drive.Attachment0 = attachment
drive.RelativeTo = Enum.ActuatorRelativeTo.World
drive.ForceLimitsEnabled = false
local originals = {}
local function disableCollision(part)
if not part:IsA("BasePart") then return end
if originals[part] == nil then originals[part] = part.CanCollide end
part.CanCollide = false
end
for _, part in ipairs(char:GetDescendants()) do disableCollision(part) end
local added = char.DescendantAdded:Connect(disableCollision)
local noclipConn = RunService.PreSimulation:Connect(function()
for part in pairs(originals) do
if part.Parent and part.CanCollide then part.CanCollide = false end
end
end)
local estimate = Planner.travelSeconds(root.Position, target, C.Speed)
local began = workspace:GetServerTimeNow()
local arrived = false
while not stopped and player.Character == char and hum.Health > 0 and workspace:GetServerTimeNow() - began <= estimate * 2 + 3 do
RunService.Heartbeat:Wait()
local delta = target - root.Position
if delta.Magnitude <= stopRadius then arrived = true; break end
drive.VectorVelocity = delta.Unit * C.Speed
end
noclipConn:Disconnect()
added:Disconnect()
for part, canCollide in pairs(originals) do
if part.Parent then part.CanCollide = canCollide end
end
drive:Destroy()
attachment:Destroy()
if previousFlight and previousFlight.Parent then
previousFlight.Enabled = flightWasEnabled
end
return arrived
end
local preparedBoat, boatSeatCleanupConnection
local function prepareDinghySeats(boat)
if not boat or not boat.Parent or preparedBoat == boat then return end
if boatSeatCleanupConnection then boatSeatCleanupConnection:Disconnect() end
preparedBoat = boat
local function removePassengerSeat(part)
if part:IsA("Seat") or (part:IsA("VehicleSeat") and part.Name ~= "VehicleSeat") then
part:Destroy()
end
end
-- Watch before scanning so seats arriving with streamed boat parts are covered too.
boatSeatCleanupConnection = boat.DescendantAdded:Connect(function(part)
if not stopped then removePassengerSeat(part) end
end)
for _, part in ipairs(boat:GetDescendants()) do removePassengerSeat(part) end
end
local function buyDinghy()
local boats = workspace:FindFirstChild("Boats") or workspace:WaitForChild("Boats", 3)
local remoteFolder = ReplicatedStorage:FindFirstChild("Remotes")
local event = remoteFolder and remoteFolder:FindFirstChild("CommF_")
if not boats or not event then return nil end
local _, root = parts()
for _, existing in ipairs(boats:GetChildren()) do
local seat = boatSeat(existing)
if seat and root and boatBelongsToPlayer(existing) and (root.Position - seat.Position).Magnitude <= 500 then
prepareDinghySeats(existing)
return existing
end
end
local seen = {}
for _, child in ipairs(boats:GetChildren()) do seen[child] = true end
local arrivals = {}
local added = boats.ChildAdded:Connect(function(child) table.insert(arrivals, child) end)
task.spawn(function() pcall(function() event:InvokeServer("BuyBoat", "Dinghy") end) end)
local deadline = workspace:GetServerTimeNow() + 8
local found
repeat
for _, boat in ipairs(arrivals) do
if boat.Parent == boats and not seen[boat] and boatBelongsToPlayer(boat) and boatSeat(boat) then
found = boat
break
end
end
if found then break end
task.wait(0.1)
until stopped or workspace:GetServerTimeNow() >= deadline
added:Disconnect()
if found then prepareDinghySeats(found) end
return found
end
local function boardBoat(boat)
prepareDinghySeats(boat)
local char, root, hum = parts()
local seat = boatSeat(boat)
if not char or not seat then return false end
seat:Sit(hum)
local deadline = workspace:GetServerTimeNow() + 2
while not stopped and workspace:GetServerTimeNow() < deadline and seat.Occupant ~= hum do task.wait(0.05) end
return seat.Occupant == hum
end
-- SMART VEHICLE/FALLBACK RESOLVER
local function getActiveVehicleOrCharacter()
local char, root, hum = parts()
if not char then return nil, nil end
if hum.SeatPart and hum.SeatPart:IsA("VehicleSeat") then
local boat = hum.SeatPart:FindFirstAncestorOfClass("Model")
if boat then
ownedBoat = boat
prepareDinghySeats(boat)
local seat = boatSeat(boat)
if seat and seat.Occupant == hum then
titleLabel.Text = "Chest Farm · 100% Boat"
return boat, seat
end
end
end
if ownedBoat and ownedBoat.Parent then
prepareDinghySeats(ownedBoat)
local seat = boatSeat(ownedBoat)
if seat and (root.Position - seat.Position).Magnitude <= 350 then
display("Boarding owned Dinghy…")
approachPosition(seat.Position + Vector3.new(0, 3, 0), 10)
if boardBoat(ownedBoat) then
titleLabel.Text = "Chest Farm · 100% Boat"
return ownedBoat, seat
end
end
end
scanDealers(true)
local nearestDealer, nearestDist = nil, math.huge
for _, dealer in ipairs(dealerList) do
local dist = (root.Position - dealer.position).Magnitude
if dist < nearestDist then
nearestDealer, nearestDist = dealer, dist
end
end
if nearestDealer and nearestDist <= 1200 then
display("Boat Dealer found! Getting Dinghy…")
if (root.Position - nearestDealer.position).Magnitude > BOAT_APPROACH_RANGE then
approachPosition(nearestDealer.position, BOAT_APPROACH_RANGE)
end
local boat = buyDinghy()
if boat then
ownedBoat = boat
local seat = boatSeat(boat)
if seat then
approachPosition(seat.Position + Vector3.new(0, 3, 0), 8)
if boardBoat(boat) then
titleLabel.Text = "Chest Farm · 100% Boat"
return boat, seat
end
end
end
end
titleLabel.Text = "Chest Farm · On Foot (Scanning)"
return nil, nil
end
-- 3D CONTINUOUS FLIGHT CONTROLLER
local persistentLinearVelocity = nil
local persistentAttachment = nil
local persistentNoclipConn = nil
local noclipChar, noclipBoat = nil, nil
local noclipOriginals = {}
local noclipAdded = {}
local function restoreFlightCollision()
for _, connection in ipairs(noclipAdded) do connection:Disconnect() end
table.clear(noclipAdded)
for part, canCollide in pairs(noclipOriginals) do
if part.Parent then part.CanCollide = canCollide end
end
table.clear(noclipOriginals)
noclipChar, noclipBoat = nil, nil
end
local function setFlightCollisionTargets(char, boat, motionPart)
if char == noclipChar and boat == noclipBoat then return end
restoreFlightCollision()
noclipChar, noclipBoat = char, boat
local function disable(part)
if not part:IsA("BasePart") then return end
if noclipOriginals[part] == nil then noclipOriginals[part] = part.CanCollide end
part.CanCollide = false
end
local function watch(container)
if not container then return end
for _, part in ipairs(container:GetDescendants()) do disable(part) end
table.insert(noclipAdded, container.DescendantAdded:Connect(disable))
end
watch(char)
watch(boat)
if motionPart then
disable(motionPart)
local ok, connected = pcall(function() return motionPart:GetConnectedParts(true) end)
if ok then for _, part in ipairs(connected) do disable(part) end end
end
if not persistentNoclipConn then
persistentNoclipConn = RunService.PreSimulation:Connect(function()
for part in pairs(noclipOriginals) do
if not part.Parent then
noclipOriginals[part] = nil
elseif part.CanCollide then
part.CanCollide = false
end
end
end)
end
end
local activeFlightCommand
local function applyFlightCommand(command, now)
local motionPart, lv, dir = command.part, command.constraint, command.direction
if stopped or not motionPart.Parent or not lv.Parent then return end
local speed = command.isBoat and math.clamp(getSinusoidalSpeed(now), SPEED_MIN, SPEED_MAX) or C.Speed
local velocity = dir * speed
if command.seat and command.seat.Parent then
-- Native propulsion must not compete with the world-space flight velocity.
command.seat.ThrottleFloat = 0
command.seat.SteerFloat = 0
end
local up = math.abs(dir.Y) > 0.999 and Vector3.new(0, 0, -1) or Vector3.yAxis
motionPart.CFrame = CFrame.lookAt(motionPart.Position, motionPart.Position + dir, up)
motionPart.AssemblyAngularVelocity = Vector3.zero
lv.VectorVelocity = velocity
motionPart.AssemblyLinearVelocity = velocity
end
-- Persistent across adjacent legs; update before physics without stopping at boundaries.
table.insert(connections, RunService.PreSimulation:Connect(function()
local command = activeFlightCommand
if command then
if command.character ~= player.Character or not command.part.Parent or not command.constraint.Parent then
activeFlightCommand = nil
return
end
applyFlightCommand(command, workspace:GetServerTimeNow())
end
end))
local function getFlightConstraint(boat, seat)
local char, root = parts()
local motionPart = seat and (seat.AssemblyRootPart or seat) or root
if not motionPart then return nil, nil end
if not persistentLinearVelocity or persistentLinearVelocity.Parent ~= motionPart then
if persistentLinearVelocity then persistentLinearVelocity:Destroy() end
if persistentAttachment then persistentAttachment:Destroy() end
persistentAttachment = Instance.new("Attachment")
persistentAttachment.Name = "ContinuousFlightAttachment"
persistentAttachment.Parent = motionPart
persistentLinearVelocity = Instance.new("LinearVelocity")
persistentLinearVelocity.Name = "ContinuousFlightVelocity"
persistentLinearVelocity.Attachment0 = persistentAttachment
persistentLinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
persistentLinearVelocity.ForceLimitsEnabled = false
persistentLinearVelocity.MaxForce = math.huge
persistentLinearVelocity.VectorVelocity = Vector3.zero
persistentLinearVelocity.Parent = motionPart
end
setFlightCollisionTargets(char, boat, motionPart)
return persistentLinearVelocity, motionPart
end
local function pauseFlight()
activeFlightCommand = nil
if persistentLinearVelocity and persistentLinearVelocity.Parent then
persistentLinearVelocity.VectorVelocity = Vector3.zero
local motionPart = persistentLinearVelocity.Parent
if motionPart:IsA("BasePart") then
motionPart.AssemblyLinearVelocity = Vector3.zero
motionPart.AssemblyAngularVelocity = Vector3.zero
end
end
end
-- Moves in a single straight 3D vector directly to the destination with INSTANT acceleration and FULL 3D PITCH
local function move3D(boat, seat, destination, recordsToArm, guard)
local char, root, hum = parts()
if not char then return "interrupted" end
local lv, motionPart = getFlightConstraint(boat, seat)
if not lv or not motionPart then return "interrupted" end
local began = workspace:GetServerTimeNow()
local startPos = root.Position
local delta = destination - startPos
local totalDist = delta.Magnitude
local function armNearby(position)
if not recordsToArm then return end
for _, rec in ipairs(recordsToArm) do
local trigger = rec.spawnPart or rec.part
local offset = trigger and trigger.CFrame:PointToObjectSpace(position)
local half = trigger and trigger.Size * 0.5
if available(trigger) and math.abs(offset.X) <= half.X + 12
and math.abs(offset.Y) <= half.Y + 12 and math.abs(offset.Z) <= half.Z + 12 then
local attempt = beginPending(rec, 0.05)
if attempt and math.abs(offset.X) <= half.X and math.abs(offset.Y) <= half.Y
and math.abs(offset.Z) <= half.Z then attempt.crossed = true end
end
end
end
armNearby(startPos)
if totalDist <= C.ArrivalDistance then return "arrived" end
local initialDir = delta.Unit
local isBoat = (boat ~= nil and seat ~= nil)
local minSpeed = isBoat and SPEED_MIN or C.Speed
local timeout = (totalDist / minSpeed) + 3.0
local outcome = "arrived"
local movingDistance, movingTime = 0, 0
local previousPosition, previousTime = motionPart.Position, os.clock()
local command = {part = motionPart, constraint = lv, direction = initialDir,
seat = seat, isBoat = isBoat, character = char}
local function drive(dir, now)
command.direction = dir
activeFlightCommand = command
applyFlightCommand(command, now)
end
drive(initialDir, began)
while not stopped and player.Character == char and hum.Health > 0 do
RunService.Heartbeat:Wait()
local frameTime = os.clock()
local framePosition = motionPart.Position
movingDistance += (framePosition - previousPosition).Magnitude
movingTime += frameTime - previousTime
previousPosition, previousTime = framePosition, frameTime
if isBoat and seat.Occupant ~= hum then
seat:Sit(hum)
if seat.Occupant ~= hum then outcome = "interrupted"; break end
end
local now = workspace:GetServerTimeNow()
if now - began > timeout then outcome = "timeout"; break end
local currentPos = root.Position
local currentDelta = destination - currentPos
local currentDist = currentDelta.Magnitude
armNearby(currentPos)
if guard then
local decision = guard(now, currentPos, currentDist)
if decision then outcome = decision; break end
end
-- Cutoff check
local passed = (currentPos - startPos):Dot(initialDir) >= totalDist
if currentDist <= C.ArrivalDistance or passed then
outcome = "arrived"
break
end
-- Each leg is a straight velocity vector; do not chase an overshot endpoint.
drive(initialDir, now)
end
if stopped or player.Character ~= char or hum.Health <= 0 then
outcome = "interrupted"
end
if outcome == "arrived" then
recordLegPerformance(movingDistance, movingTime, isBoat and "boat" or "foot")
elseif outcome == "timeout" or outcome == "interrupted" then
pauseFlight()
end
return outcome
end
-- One short pass collects every chest in an overlapping trigger cluster.
local function flyThroughTarget(boat, seat, node)
local char, root = parts()
if not char then return "interrupted" end
local recordsList = node.records
local entryPoint, centerPoint, exitPoint = Planner.sweepPath(node, root.Position, C.SweepMargin)
currentTargetBoxCenter, currentTargetRecords = centerPoint, recordsList
local function finish(outcome)
currentRouteDestination, currentTargetBoxCenter = nil, nil
currentTargetRecords, currentNextRoutePosition = nil, nil
return outcome
end
local function hasActive()
for _, record in ipairs(recordsList) do
if available(record.spawnPart or record.part) then return true end
end
return false
end
local function hasMissing()
for _, record in ipairs(recordsList) do if not loadedTrigger(record) then return true end end
return false
end
local function hasPotential(now, seconds)
for _, record in ipairs(recordsList) do
if rememberedReadyAt(record, now) <= now + seconds then return true end
end
return false
end
local approachSeconds = Planner.travelSeconds(root.Position, entryPoint, liveNavigation.speed)
if not hasPotential(workspace:GetServerTimeNow(), approachSeconds) then return finish("unavailable") end
local verificationJob
local began, lastReplan = workspace:GetServerTimeNow(), workspace:GetServerTimeNow()
local targetName = node.isCluster and ("Pass · " .. #recordsList .. " chests") or node.record.name
local function guard(now, position, remaining)
if not hasPotential(now, Planner.travelSeconds(position, entryPoint, liveNavigation.speed)) then return "unavailable" end
if hasMissing() and not verificationJob and remaining <= liveNavigation.speed * STREAM_TIMEOUT + DISCOVERY_RADIUS then
verificationJob = requestStream(centerPoint)
end
if remaining <= C.FinishDistance or now - began < C.MinimumCommitSeconds
or now - lastReplan < C.ReplanSeconds then return end
-- Finish the short pass once contact is possible; never reroute during confirmation.
for _, record in ipairs(recordsList) do
if record.pendingAttempt then return end
end
lastReplan = now
refreshChests()
local _, currentRoot = parts()
if not currentRoot then return "interrupted" end
local best = choose(currentRoot, nil, liveNavigation.speed)
if not best then return "unavailable" end
local sameTarget = best.first.id == node.id
local retained = sameTarget and best or choose(currentRoot, node.record, liveNavigation.speed)
if not sameTarget and (not retained or best.score > retained.score * C.SwitchGain) then
return "reroute"
end
-- Preserve the displayed committed route when a marginal alternative is rejected.
if retained then
liveNavigation.plan = retained
currentNextRoutePosition = retained.route[2] and retained.route[2].position or nil
end
end
display("Approach · " .. targetName)
currentRouteDestination = entryPoint
local approach = move3D(boat, seat, entryPoint, recordsList, guard)
if approach ~= "arrived" then return finish(approach) end
refreshChests(true)
if not hasActive() and hasMissing() then
if workspace.StreamingEnabled then
verificationJob = verificationJob or requestStream(centerPoint)
pauseFlight()
local deadline = workspace:GetServerTimeNow() + STREAM_TIMEOUT
while not stopped and not hasActive() and workspace:GetServerTimeNow() < deadline do
RunService.Heartbeat:Wait()
refreshChests()
local allLoaded = true
for _, record in ipairs(recordsList) do if not loadedTrigger(record) then allLoaded = false; break end end
if allLoaded then break end
if not verificationJob then verificationJob = requestStream(centerPoint) end
end
refreshChests(true)
end
end
if stopped then return finish("interrupted") end
if not hasActive() then
for _, record in ipairs(recordsList) do
if not loadedTrigger(record) then record.cooldown = workspace:GetServerTimeNow() + C.ChestFailureCooldown end
end
return finish("unavailable")
end
display("Passing through · " .. targetName)
currentRouteDestination = exitPoint
-- No timer wait and no artificial confirmation pause: continue through the hitboxes.
return finish(move3D(boat, seat, exitPoint, recordsList))
end
-- Loaded inactivity wins. Remembered data is usable only when its hitbox is unloaded.
eligible = function(record, now)
local pending = record.pendingAttempt
return rememberedReadyAt(record, now) < math.huge
and not (pending and not pending.done)
and now >= (record.cooldown or 0)
end
-- Conservatively inscribe an axis-aligned cube in a rotated hitbox.
local function triggerBounds(record)
local geometry = record.geometry
if geometry.low then return geometry.low, geometry.high end
local half = geometry.size * 0.5
local rotation = geometry.cframe
local right, up, look = rotation.RightVector, rotation.UpVector, rotation.LookVector
local radius = math.min(
half.X / (math.abs(right.X) + math.abs(right.Y) + math.abs(right.Z)),
half.Y / (math.abs(up.X) + math.abs(up.Y) + math.abs(up.Z)),
half.Z / (math.abs(look.X) + math.abs(look.Y) + math.abs(look.Z)))
local extent = Vector3.new(radius, radius, radius)
local low, high = rotation.Position - extent, rotation.Position + extent
low = Vector3.new(low.X, math.max(low.Y, C.MinRootY), low.Z)
geometry.low, geometry.high = low, high
return low, high
end
local function overlapBounds(aLow, aHigh, bLow, bHigh)
local low = Vector3.new(math.max(aLow.X, bLow.X), math.max(aLow.Y, bLow.Y), math.max(aLow.Z, bLow.Z))
local high = Vector3.new(math.min(aHigh.X, bHigh.X), math.min(aHigh.Y, bHigh.Y), math.min(aHigh.Z, bHigh.Z))
return low, high
end
local function buildFusedClusters(rawNodes)
local nodes, used = {}, {}
for index, anchor in ipairs(rawNodes) do
if used[index] then continue end
local group, low, high = {anchor.record}, anchor.low, anchor.high
local value, expected, readyAt = anchor.value, anchor.value * anchor.reliability, anchor.readyAt
used[index] = true
for other = index + 1, #rawNodes do
if used[other] then continue end
local candidate = rawNodes[other]
if anchor.inferred ~= candidate.inferred or math.abs(readyAt - candidate.readyAt) > 3 then continue end
if candidate.low.X > high.X - 4 or candidate.high.X < low.X + 4
or candidate.low.Y > high.Y - 4 or candidate.high.Y < low.Y + 4
or candidate.low.Z > high.Z - 4 or candidate.high.Z < low.Z + 4 then continue end
local nextLow, nextHigh = overlapBounds(low, high, candidate.low, candidate.high)
local span = nextHigh - nextLow
-- Every member shares a real touch region; one short pass can collect all.
if math.min(span.X, span.Y, span.Z) >= 4 then
low, high = nextLow, nextHigh
value += candidate.value
expected += candidate.value * candidate.reliability
readyAt = math.max(readyAt, candidate.readyAt)
table.insert(group, candidate.record)
used[other] = true
end
end
table.insert(nodes, {id = anchor.record.id, record = anchor.record, records = group,
position = (low + high) * 0.5, halfSize = (high - low) * 0.5,
value = value, reliability = expected / value,
readyAt = readyAt, inferred = anchor.inferred,
isCluster = #group > 1, clusterCount = #group})
end
return nodes
end
local function snapshotNodes(now)
local raw = {}
for _, record in ipairs(records) do
if not eligible(record, now) then continue end
local low, high = triggerBounds(record)
if high.Y <= low.Y then continue end
local reward = economyOf(record).rewards[REWARD_SEA]
local inferred = loadedTrigger(record) == nil
table.insert(raw, {record = record, low = low, high = high, value = (reward[1] + reward[2]) * 0.5,
readyAt = rememberedReadyAt(record, now), inferred = inferred,
reliability = math.clamp((record.successes + 8) / (record.successes + record.misses + 8), 0.3, 1)
* (inferred and 0.85 or 1)})
end
return buildFusedClusters(raw)
end
local function plannerOptions(speed)
return {speed = speed, maxTravel = MAX_TRAVEL_SECONDS,
travelEstimator = function(from, dest) return Planner.travelSeconds(from, dest, speed) end,
service = ESTIMATED_PICKUP_SECONDS, sweepMargin = C.SweepMargin,
depth = LOOKAHEAD_STOPS, width = C.BeamWidth, branch = C.BranchWidth,
smoothing = 5, budget = C.PlanBudgetSeconds}
end
choose = function(root, forcedRecord, currentSpeed)
local now, began = workspace:GetServerTimeNow(), os.clock()
local nodes = snapshotNodes(now)
local plan = Planner.plan(root.Position, nodes, now, plannerOptions(currentSpeed or C.BoatSpeed),
forcedRecord and forcedRecord.id)
if plan then plan.node, plan.record = plan.first, plan.first.record end
if not forcedRecord then
liveNavigation.plan = plan
liveNavigation.nodeCount, liveNavigation.planMilliseconds = #nodes, (os.clock() - began) * 1000
end
return plan
end
-- Discovery visits chest locations only and expands as more chest parts stream in.
-- It is separate from dynamic farming and never treats a visit as collection evidence.
local function addDiscoveryRegion(record)
local position = enforceAltitudeFloor(record.position)
for _, region in ipairs(discovery.regions) do
if (region.position - position).Magnitude <= DISCOVERY_RADIUS then return end
end
table.insert(discovery.regions, {position = position, name = record.name, record = record, visits = 0})
end
local function collectDiscoverySeeds(force)
if not discovery.active then return end
local now = os.clock()
if not force and now - discovery.lastSeedScan < 1 then return end
discovery.lastSeedScan = now
for _, record in ipairs(records) do
if not discovery.seededRecords[record.id] then
discovery.seededRecords[record.id] = true
addDiscoveryRegion(record)
end
end
end
local function discoveryNode(region)
if region.record.geometry then
local low, high = triggerBounds(region.record)
return {position = (low + high) * 0.5, halfSize = (high - low) * 0.5}
end
return {position = region.position}
end
local function chooseDiscovery(root, speed)
collectDiscoverySeeds(true)
local nearest, distance
for _, region in ipairs(discovery.regions) do
local trigger = loadedTrigger(region.record)
if not region.visited and trigger and not trigger.CanTouch then
-- Its state is already observed; discovery does not need a trip to an empty chest.
region.visited = true
discovery.completed += 1
end
if not region.visited then
local entry = Planner.sweepPath(discoveryNode(region), root.Position, C.SweepMargin)
local candidate = Planner.travelSeconds(root.Position, entry, speed)
if candidate <= MAX_TRAVEL_SECONDS and (not distance or candidate < distance) then
nearest, distance = region, candidate
end
end
end
if not nearest then
for _, region in ipairs(discovery.regions) do
if not region.visited then region.visited = true; discovery.skipped += 1 end
end
discovery.active = false
log(string.format("Discovery complete: %d areas sampled, %d chest locations remembered, %d far areas skipped",
discovery.completed, #records, discovery.skipped))
end
return nearest
end
local function discoverArea(boat, seat, region)
local _, root = parts()
if not root then return "interrupted" end
local entryPoint, centerPoint, exitPoint = Planner.sweepPath(discoveryNode(region), root.Position, C.SweepMargin)
local nearRecords = {}
for _, record in ipairs(records) do
if (record.position - region.position).Magnitude <= DISCOVERY_RADIUS then table.insert(nearRecords, record) end
end
liveNavigation.plan = nil
currentRouteDestination, currentTargetRecords = entryPoint, nearRecords
currentTargetBoxCenter, currentNextRoutePosition = centerPoint, nil
display(string.format("Discovering %d/%d · %s", discovery.completed + 1, #discovery.regions, region.name))
local job
local knownRecordCount = #records
local function streamGuard(_, _, remaining)
refreshChests()
local trigger = loadedTrigger(region.record)
if trigger and not trigger.CanTouch then return "unavailable" end
for index = knownRecordCount + 1, #records do
local record = records[index]
if (record.position - region.position).Magnitude <= DISCOVERY_RADIUS then
table.insert(nearRecords, record)
end
end
knownRecordCount = #records
if not job and remaining <= liveNavigation.speed * STREAM_TIMEOUT + DISCOVERY_RADIUS then
job = requestStream(region.position)
end
end
local outcome = move3D(boat, seat, entryPoint, nearRecords, streamGuard)
if outcome == "arrived" then
if workspace.StreamingEnabled and not loadedTrigger(region.record) and (not job or not job.done) then
job = job or requestStream(region.position)
pauseFlight()
local deadline = workspace:GetServerTimeNow() + STREAM_TIMEOUT
repeat
RunService.Heartbeat:Wait()
refreshChests()
if not job then job = requestStream(region.position) end
until stopped or loadedTrigger(region.record) or (job and job.done) or workspace:GetServerTimeNow() >= deadline
end
refreshChests(true)
collectDiscoverySeeds(true)
if available(loadedTrigger(region.record)) then
currentRouteDestination = exitPoint
outcome = move3D(boat, seat, exitPoint, nearRecords)
end
if outcome == "arrived" then
region.visited = true
discovery.completed += 1
elseif outcome == "timeout" then
region.visits += 1
if region.visits >= 2 then region.visited = true; discovery.skipped += 1 end
end
elseif outcome == "timeout" then
region.visits += 1
if region.visits >= 2 then region.visited = true; discovery.skipped += 1 end
end
currentRouteDestination, currentTargetBoxCenter = nil, nil
currentTargetRecords, currentNextRoutePosition = nil, nil
return outcome
end
updateSmallDetails = function()
local ready, expected, waiting, confirmed, loaded = 0, 0, 0, 0, 0
local now = workspace:GetServerTimeNow()
for _, record in ipairs(records) do
confirmed += record.successes or 0
if loadedTrigger(record) then loaded += 1 end
local state = chestStatus(record, now)
if state == "ready" then ready += 1
elseif state == "remembered" then expected += 1
else waiting += 1 end
end
availabilityLabel.Text = string.format("%d live · %d expected · %d cooling/empty", ready, expected, waiting)
if discovery.active then
nextPassLabel.Text = string.format("Discovery %d/%d areas · %d known chests",
discovery.completed + discovery.skipped, #discovery.regions, #records)
plannerLabel.Text = string.format("%d loaded · %d confirmed · learning locations", loaded, confirmed)
return
end
local plan = liveNavigation.plan
if plan then
local _, root = parts()
local seconds = root and Planner.travelSeconds(root.Position,
Planner.sweepPath(plan.first, root.Position, C.SweepMargin), liveNavigation.speed or C.BoatSpeed) or 0
nextPassLabel.Text = string.format("Next pass ~%s · ETA %.1fs", formatMoney(plan.first.value), seconds)
else
nextPassLabel.Text = "Watching known chest respawns…"
end
plannerLabel.Text = string.format("%d confirmed · %d candidate stops · %d ahead",
confirmed, liveNavigation.nodeCount, plan and #plan.route or 0)
end
local function installChestMap()
if not LOAD_UI then return end
local inputService = game:GetService("UserInputService")
local guiService = game:GetService("GuiService")
local colors = {
ready = Color3.fromRGB(99, 225, 160), predicted = Color3.fromRGB(255, 204, 111),
remembered = Color3.fromRGB(125, 190, 255),
unknown = Color3.fromRGB(126, 166, 231), empty = Color3.fromRGB(113, 125, 143),
target = Color3.fromRGB(255, 113, 132), dealer = Color3.fromRGB(186, 147, 247),
}
local function rounded(object, radius)
Instance.new("UICorner", object).CornerRadius = UDim.new(0, radius)
end
local function text(parent, value, size, color)
local item = Instance.new("TextLabel")
item.BackgroundTransparency = 1
item.Font = Enum.Font.Gotham
item.TextSize = size
item.TextColor3 = color or light
item.TextXAlignment = Enum.TextXAlignment.Left
item.TextTruncate = Enum.TextTruncate.AtEnd
item.Text = value
item.Parent = parent
return item
end
local frame = Instance.new("Frame")
frame.Name = "ChestMap"
frame.Visible = false
frame.AnchorPoint = Vector2.new(1, 0)
frame.BackgroundColor3 = Color3.fromRGB(19, 24, 33)
frame.BorderSizePixel = 0
frame.Parent = gui
rounded(frame, 12)
local border = Instance.new("UIStroke", frame)
border.Color = Color3.fromRGB(57, 69, 87)
local heading = text(frame, "CHEST MAP · LIVE ROUTE", 16)
heading.Font = Enum.Font.GothamBold
heading.Position, heading.Size = UDim2.fromOffset(14, 10), UDim2.new(1, -64, 0, 24)
local subtitle = text(frame, "Finding nearby spawns…", 11, muted)
subtitle.Position, subtitle.Size = UDim2.fromOffset(14, 36), UDim2.new(1, -28, 0, 18)
local function button(value, x, width, y)
local item = Instance.new("TextButton")
item.Text, item.Font, item.TextSize = value, Enum.Font.GothamMedium, 12
item.TextColor3 = light
item.BackgroundColor3 = Color3.fromRGB(38, 47, 62)
item.BorderSizePixel = 0
item.Position, item.Size = UDim2.fromOffset(x, y or 62), UDim2.fromOffset(width, 32)
item.Parent = frame
rounded(item, 6)
return item
end
local fitButton = button("Fit", 12, 42)
local followButton = button("Follow", 60, 62)
local timersButton = button("Timers Off", 128, 88)
local minusButton = button("−", 222, 32)
local plusButton = button("+", 260, 32)
local closeButton = button("×", 0, 30, 8)
closeButton.Position = UDim2.new(1, -42, 0, 8)
local canvas = Instance.new("Frame")
canvas.Position, canvas.Size = UDim2.fromOffset(12, 104), UDim2.new(1, -24, 1, -234)
canvas.BackgroundColor3 = Color3.fromRGB(25, 33, 45)
canvas.BorderSizePixel = 0
canvas.ClipsDescendants = true
canvas.Parent = frame
local function footer(value, y, height, size)
local item = text(frame, value, size or 11, muted)
item.Position, item.Size = UDim2.new(0, 14, 1, y), UDim2.new(1, -28, 0, height)
return item
end
local legend = footer('', -120, 18, 11)
legend.RichText = true
legend.Text = '<font color="#63E1A0">●</font> Live <font color="#7DBEFF">●</font> Expected <font color="#FFCC6F">●</font> Cooling'
local legend2 = footer('', -102, 18, 11)
legend2.RichText = true
legend2.Text = '<font color="#717D8F">●</font> Empty <font color="#FF7184">●</font> Target <font color="#BA93F7">◆</font> Dealer <font color="#FFFFFF">▲</font> You'
local help = footer("Drag to pan · Tap a group to zoom · S / G / D = grade", -81, 18, 10)
local details = footer("Tap a chest for its value, distance and respawn time.", -60, 50, 12)
details.TextWrapped, details.TextTruncate = true, Enum.TextTruncate.None
details.TextYAlignment = Enum.TextYAlignment.Top
details.TextColor3 = light
local center, pixelsPerStud = Vector2.zero, 0.1
local initialized, follow, timers = false, false, false
local autoFitUntil, fittedRecordCount = os.clock() + 2, 0
local selected, selectedGroup = nil, nil
local dirty, lastRefresh, suppressClickUntil = true, 0, 0
local markerPool, dealerPool, gridPool = {}, {}, {}
local lastViewport = Vector2.zero
local function flat(position) return Vector2.new(position.X, position.Z) end
local function project(position)
local delta = flat(position) - center
return canvas.AbsoluteSize * 0.5 + Vector2.new(delta.X, -delta.Y) * pixelsPerStud
end
local function unproject(point)
local delta = (point - canvas.AbsoluteSize * 0.5) / pixelsPerStud
return center + Vector2.new(delta.X, -delta.Y)
end
local function isInRange(position, root)
return not root or (flat(position) - flat(root.Position)).Magnitude <= MAP_OUTLIER_DISTANCE
end
local function countdown(seconds)
local value = math.max(0, math.ceil(seconds))
return string.format("%d:%02d", math.floor(value / 60), value % 60)
end
local function status(record, now)
return chestStatus(record, now)
end
local function setFollow(value)
follow = value
followButton.Text = value and "Following" or "Follow"
followButton.BackgroundColor3 = value and Color3.fromRGB(39, 87, 100) or Color3.fromRGB(38, 47, 62)
end
local function fit()
local _, root = parts()
if not root then return end
local low, high = Vector2.new(math.huge, math.huge), Vector2.new(-math.huge, -math.huge)
local count = 0
local function include(position)
local p = flat(position)
low = Vector2.new(math.min(low.X, p.X), math.min(low.Y, p.Y))
high = Vector2.new(math.max(high.X, p.X), math.max(high.Y, p.Y))
end
for _, record in ipairs(records) do
if isInRange(record.position, root) then include(record.position); count += 1 end
end
if root then include(root.Position) end
if low.X == math.huge then return end
center = (low + high) * 0.5
local size, span = canvas.AbsoluteSize, high - low
pixelsPerStud = math.clamp(math.min(math.max(40, size.X - 64) / math.max(200, span.X),
math.max(40, size.Y - 64) / math.max(200, span.Y)), 0.002, 4)
initialized = count > 0
setFollow(false)
dirty = true
end
local function zoom(factor, point)
autoFitUntil = 0
point = point or canvas.AbsoluteSize * 0.5
local before = unproject(point)
pixelsPerStud = math.clamp(pixelsPerStud * factor, 0.002, 4)
center += before - unproject(point)
setFollow(false)
dirty = true
end
local function line(color, thickness)
local item = Instance.new("Frame")
item.BorderSizePixel, item.BackgroundColor3 = 0, color
item.AnchorPoint = Vector2.new(0.5, 0.5)
item.ZIndex = 2
item.Size = UDim2.fromOffset(0, thickness or 2)
item.Parent = canvas
return item
end
local routeLine, nextLine = line(Color3.fromRGB(88, 205, 237)), line(colors.predicted)
routeLine.ZIndex, nextLine.ZIndex = 3, 3
local lookaheadLines = {}
local function drawLine(item, a, b)
item.Visible = a ~= nil and b ~= nil
if not item.Visible then return end
-- Clip before rotating so a long route cannot spill across the surrounding UI.
local travel, enter, leave = b - a, 0, 1
local function clip(p, q)
if math.abs(p) < 1e-9 then return q >= 0 end
local ratio = q / p
if p < 0 then enter = math.max(enter, ratio) else leave = math.min(leave, ratio) end
return enter <= leave
end
local bounds = canvas.AbsoluteSize
if not (clip(-travel.X, a.X) and clip(travel.X, bounds.X - a.X)
and clip(-travel.Y, a.Y) and clip(travel.Y, bounds.Y - a.Y)) then
item.Visible = false
return
end
b, a = a + travel * leave, a + travel * enter
local delta, midpoint = b - a, (a + b) * 0.5
item.Position, item.Size = UDim2.fromOffset(midpoint.X, midpoint.Y),
UDim2.fromOffset(delta.Magnitude, item.Size.Y.Offset)
item.Rotation = math.deg(math.atan2(delta.Y, delta.X))
end
local playerDot = text(canvas, "▲", 23, Color3.new(1, 1, 1))
playerDot.AnchorPoint, playerDot.Size = Vector2.new(0.5, 0.5), UDim2.fromOffset(26, 26)
playerDot.TextXAlignment, playerDot.ZIndex = Enum.TextXAlignment.Center, 7
playerDot.TextStrokeTransparency = 0.3
local scaleLabel = text(canvas, "", 10, muted)
scaleLabel.Position, scaleLabel.Size, scaleLabel.ZIndex = UDim2.fromOffset(8, 6), UDim2.new(1, -16, 0, 16), 8
local function newMarker()
local item = {}
item.button = Instance.new("TextButton")
local b = item.button
b.AnchorPoint, b.Size = Vector2.new(0.5, 0.5), UDim2.fromOffset(inputService.TouchEnabled and 34 or 24, inputService.TouchEnabled and 34 or 24)
b.Font, b.TextSize, b.TextColor3 = Enum.Font.GothamBold, 11, Color3.fromRGB(17, 24, 33)
b.BorderSizePixel, b.ZIndex, b.Parent = 0, 4, canvas
rounded(b, 12)
item.stroke = Instance.new("UIStroke", b)
item.stroke.ApplyStrokeMode, item.stroke.Thickness = Enum.ApplyStrokeMode.Border, 2
item.timer = text(canvas, "", 10, colors.predicted)
item.timer.BackgroundColor3, item.timer.BackgroundTransparency = Color3.fromRGB(15, 21, 30), 0.05
item.timer.TextXAlignment, item.timer.Size, item.timer.ZIndex = Enum.TextXAlignment.Center, UDim2.fromOffset(52, 18), 6
rounded(item.timer, 4)
table.insert(connections, b.Activated:Connect(function()
if os.clock() < suppressClickUntil or not item.group then return end
local group = item.group
selectedGroup, selected = group.records, group.records[1]
if #group.records > 1 then
if pixelsPerStud >= 4 then
item.inspectIndex = (item.inspectIndex or 0) % #group.records + 1
selected, selectedGroup = group.records[item.inspectIndex], nil
else
center = group.world / #group.records
pixelsPerStud = math.min(4, pixelsPerStud * 2.2)
end
autoFitUntil = 0
setFollow(false)
end
dirty = true
end))
return item
end
local function layout()
local viewport = workspace.CurrentCamera and workspace.CurrentCamera.ViewportSize or Vector2.new(1000, 700)
if not gui.IgnoreGuiInset then
local topLeft, bottomRight = guiService:GetGuiInset()
viewport -= topLeft + bottomRight
end
if viewport == lastViewport then return end
lastViewport = viewport
local touch = inputService.TouchEnabled
local width = math.max(260, math.min(520, viewport.X - 16))
local height = math.max(240, math.min(600, viewport.Y - 16))
frame.Size = UDim2.fromOffset(width, height)
frame.Position = UDim2.new(1, -8, 0, touch and 8 or math.min(76, math.max(8, (viewport.Y - height) * 0.5)))
local controls = {fitButton, followButton, timersButton, minusButton, plusButton}
local controlWidth = (width - 40) / #controls
for index, control in ipairs(controls) do
control.Size = UDim2.fromOffset(controlWidth, touch and 42 or 32)
control.Position = UDim2.fromOffset(12 + (index - 1) * (controlWidth + 4), 60)
control.TextSize = controlWidth < 65 and 10 or 12
end
closeButton.Size = UDim2.fromOffset(touch and 42 or 30, touch and 42 or 32)
closeButton.Position = UDim2.new(1, touch and -50 or -42, 0, 6)
local compact = height < 430
local canvasTop = touch and 110 or 104
local footerHeight = compact and 108 or 130
canvas.Position = UDim2.fromOffset(12, canvasTop)
canvas.Size = UDim2.new(1, -24, 1, -canvasTop - footerHeight)
legend.Visible = not compact
legend2.Position = UDim2.new(0, 14, 1, compact and -98 or -102)
help.Position = UDim2.new(0, 14, 1, compact and -78 or -81)
details.Position = UDim2.new(0, 14, 1, -58)
details.TextSize = compact and 11 or 12
panel.Visible = not (touch and frame.Visible)
dirty = true
end
local function render()
local _, root = parts()
local now, size = workspace:GetServerTimeNow(), canvas.AbsoluteSize
if size.X <= 0 or size.Y <= 0 then return end
if not initialized or (#records ~= fittedRecordCount and os.clock() < autoFitUntil) then
fit()
fittedRecordCount = #records
end
if follow and root then center = flat(root.Position) end
local targets = {}
for _, record in ipairs(currentTargetRecords or {}) do targets[record] = true end
local groups, bins = {}, {}
local ready, expected, respawning, omitted, visible = 0, 0, 0, 0, 0
for _, record in ipairs(records) do
if not isInRange(record.position, root) then omitted += 1; continue end
local state, p = status(record, now), project(record.position)
if state == "ready" then ready += 1 elseif state == "remembered" then expected += 1
elseif state == "predicted" then respawning += 1 end
local markerInset = inputService.TouchEnabled and 19 or 14
if p.X < markerInset or p.Y < 26 or p.X > size.X - markerInset or p.Y > size.Y - markerInset then continue end
visible += 1
local spacing = inputService.TouchEnabled and 42 or 30
local bx, by = math.floor(p.X / spacing), math.floor(p.Y / spacing)
local group
for x = bx - 1, bx + 1 do
for y = by - 1, by + 1 do
for _, candidate in ipairs(bins[x .. ":" .. y] or {}) do
if (candidate.point - p).Magnitude < spacing then group = candidate; break end
end
if group then break end
end
if group then break end
end
if not group then
group = {point = p, world = Vector2.zero, records = {}, ready = 0, target = false, state = state}
table.insert(groups, group)
local key = bx .. ":" .. by
bins[key] = bins[key] or {}
table.insert(bins[key], group)
end
table.insert(group.records, record)
group.world += flat(record.position)
group.target = group.target or targets[record] == true
if state == "ready" then group.ready += 1; group.state = "ready" end
if state == "remembered" and group.ready == 0 then group.state = "remembered" end
if state == "predicted" then
group.remaining = math.min(group.remaining or math.huge, record.readyAt - now)
if group.ready == 0 and group.state ~= "remembered" then group.state = "predicted" end
end
end
-- A world-aligned grid and distance key give scale without inventing terrain.
local rawStep = 70 / pixelsPerStud
local power = 10 ^ math.floor(math.log10(rawStep))
local step = math.ceil(rawStep / power) * power
local topLeft = unproject(Vector2.zero)
local gridCount = 0
local function gridLine(position, dimensions)
gridCount += 1
local item = gridPool[gridCount]
if not item then
item = Instance.new("Frame")
item.BackgroundColor3, item.BorderSizePixel, item.ZIndex, item.Parent = Color3.fromRGB(36, 46, 61), 0, 1, canvas
gridPool[gridCount] = item
end
item.Position, item.Size, item.Visible = position, dimensions, true
end
local firstX = (math.ceil(topLeft.X / step) * step - topLeft.X) * pixelsPerStud
local firstY = (topLeft.Y - math.floor(topLeft.Y / step) * step) * pixelsPerStud
for x = firstX, size.X, step * pixelsPerStud do gridLine(UDim2.fromOffset(x, 0), UDim2.fromOffset(1, size.Y)) end
for y = firstY, size.Y, step * pixelsPerStud do gridLine(UDim2.fromOffset(0, y), UDim2.fromOffset(size.X, 1)) end
for i = gridCount + 1, #gridPool do gridPool[i].Visible = false end
local route = liveNavigation.plan and liveNavigation.plan.route or {}
scaleLabel.Text = string.format("+Z ↑ · grid %s · purple: lookahead · cyan: current · gold: next", tostring(step))
local segmentCount = math.max(0, #route - 1)
local createdSegments = 0
for index = 1, segmentCount do
local segment = lookaheadLines[index]
if not segment then
if createdSegments >= 24 then dirty = true; break end
segment = line(Color3.fromRGB(180, 115, 255), 2)
segment.BackgroundTransparency = 0.25
local direction = text(segment, "▶", 12, Color3.fromRGB(216, 174, 255))
direction.Name = "Direction"
direction.AnchorPoint = Vector2.new(0.5, 0.5)
direction.Position = UDim2.new(0.62, 0, 0.5, 0)
direction.Size = UDim2.fromOffset(14, 14)
direction.TextXAlignment = Enum.TextXAlignment.Center
direction.TextStrokeTransparency = 0.35
direction.ZIndex = 2
lookaheadLines[index] = segment
createdSegments += 1
end
local fromStop, toStop = route[index], route[index + 1]
if isInRange(fromStop.position, root) and isInRange(toStop.position, root) then
drawLine(segment, project(fromStop.position), project(toStop.position))
else
segment.Visible = false
end
local direction = segment:FindFirstChild("Direction")
if direction then direction.Visible = segment.Visible and segment.Size.X.Offset >= 26 end
end
for index = segmentCount + 1, #lookaheadLines do lookaheadLines[index].Visible = false end
-- Place timer labels only in free space; the selected chest always has a detailed countdown below.
local occupied = {}
for _, group in ipairs(groups) do
table.insert(occupied, {group.point.X - 14, group.point.Y - 14, group.point.X + 14, group.point.Y + 14})
end
for i, group in ipairs(groups) do
local item = markerPool[i]
if not item then item = newMarker(); markerPool[i] = item end
item.group = group
local b, p = item.button, group.point
b.Visible, b.Position = true, UDim2.fromOffset(p.X, p.Y)
b.BackgroundColor3 = colors[group.state]
b.Text = #group.records > 1 and tostring(#group.records) or gradeOf(group.records[1]):sub(1, 1)
item.stroke.Color = group.target and colors.target or (selected and table.find(group.records, selected) and light or Color3.fromRGB(15, 22, 32))
item.stroke.Thickness = group.target and 3 or 2
item.timer.Visible = false
if timers and group.remaining then
for _, offset in ipairs({Vector2.new(-26, -34), Vector2.new(-26, 16), Vector2.new(16, -9), Vector2.new(-68, -9)}) do
local origin = p + offset
local rect = {origin.X, origin.Y, origin.X + 52, origin.Y + 18}
local free = rect[1] >= 0 and rect[2] >= 24 and rect[3] <= size.X and rect[4] <= size.Y
if free then
for _, other in ipairs(occupied) do
if rect[1] < other[3] and rect[3] > other[1] and rect[2] < other[4] and rect[4] > other[2] then free = false; break end
end
end
if free then
item.timer.Position = UDim2.fromOffset(origin.X, origin.Y)
item.timer.Text = "~" .. countdown(group.remaining)
item.timer.Visible = true
table.insert(occupied, rect)
break
end
end
end
end
for i = #groups + 1, #markerPool do markerPool[i].button.Visible = false; markerPool[i].timer.Visible = false end
local dealerCount = 0
for _, dealer in ipairs(dealerList) do
if dealer.instance and isInRange(dealer.position, root) then
local p = project(dealer.position)
if p.X >= 12 and p.Y >= 24 and p.X <= size.X - 12 and p.Y <= size.Y - 12 then
dealerCount += 1
local item = dealerPool[dealerCount]
if not item then
item = text(canvas, "◆", 19, colors.dealer)
item.AnchorPoint, item.Size, item.ZIndex = Vector2.new(0.5, 0.5), UDim2.fromOffset(20, 20), 3
item.TextXAlignment = Enum.TextXAlignment.Center
dealerPool[dealerCount] = item
end
item.Position, item.Visible = UDim2.fromOffset(p.X, p.Y), true
end
end
end
for i = dealerCount + 1, #dealerPool do dealerPool[i].Visible = false end
playerDot.Visible = root ~= nil
if root then
local p, look = project(root.Position), root.CFrame.LookVector
playerDot.Position = UDim2.fromOffset(p.X, p.Y)
playerDot.Rotation = math.deg(math.atan2(look.X, look.Z))
end
drawLine(routeLine, root and project(root.Position), currentRouteDestination and project(currentRouteDestination))
drawLine(nextLine, currentTargetBoxCenter and project(currentTargetBoxCenter), currentNextRoutePosition and project(currentNextRoutePosition))
subtitle.Text = string.format("%d live · %d expected · %d cooling · %d far hidden", ready, expected, respawning, omitted)
help.Text = string.format("%d in view · Drag to pan · Tap groups to zoom · S/G/D = grade", visible)
if selected then
local state = status(selected, now)
local reward = economyOf(selected).rewards[REWARD_SEA]
local distance = root and (selected.position - root.Position).Magnitude or 0
if selectedGroup and #selectedGroup > 1 then
local groupReady, value = 0, 0
for _, record in ipairs(selectedGroup) do
if status(record, now) == "ready" then groupReady += 1 end
local range = economyOf(record).rewards[REWARD_SEA]
value += (range[1] + range[2]) * 0.5
end
local hint = pixelsPerStud >= 4 and "Tap the group again to inspect each overlapping chest."
or "Zoom in, then tap a letter to inspect a single chest."
details.Text = string.format("%d chests · %d ready · ~%s total value\n%s", #selectedGroup, groupReady, formatMoney(value), hint)
else
local stateText = state == "predicted" and ((selected.initiallyEmptyAt and "Ready by ~" or "Respawn ~") .. countdown(selected.readyAt - now))
or state == "remembered" and "Expected ready · unloaded"
or state == "unknown" and "Unverified / streamed out"
or state == "ready" and "Ready to collect" or "Empty"
details.Text = string.format("%s · %s · %.0f studs\n%s · %s–%s · %d confirmed pickups",
gradeOf(selected), selected.name, distance,
stateText, formatMoney(reward[1]), formatMoney(reward[2]), selected.successes or 0)
end
else
local plan = liveNavigation.plan
if plan then
details.Text = string.format("Next pass: %d chests · ~%s value\n%d stops ahead · blue = expected while unloaded",
#plan.first.records, formatMoney(plan.first.value), #plan.route)
else
details.Text = "Locations and states stay in memory when unloaded.\nTap a chest for value, distance and respawn time."
end
end
end
table.insert(connections, fitButton.Activated:Connect(fit))
table.insert(connections, followButton.Activated:Connect(function() setFollow(not follow); dirty = true end))
table.insert(connections, plusButton.Activated:Connect(function() zoom(1.6) end))
table.insert(connections, minusButton.Activated:Connect(function() zoom(1 / 1.6) end))
table.insert(connections, timersButton.Activated:Connect(function()
timers = not timers
timersButton.Text = timers and "Timers On" or "Timers Off"
timersButton.BackgroundColor3 = timers and Color3.fromRGB(87, 71, 38) or Color3.fromRGB(38, 47, 62)
dirty = true
end))
local function toggle()
frame.Visible = not frame.Visible
panel.Visible = not (inputService.TouchEnabled and frame.Visible)
mapButton.BackgroundColor3 = frame.Visible and Color3.fromRGB(45, 75, 95) or Color3.fromRGB(55, 60, 70)
dirty = true
end
table.insert(connections, closeButton.Activated:Connect(toggle))
table.insert(connections, mapButton.Activated:Connect(toggle))
local dragInput, dragStart, dragCenter, dragged
local function inside(position)
local inset = not gui.IgnoreGuiInset and guiService:GetGuiInset() or Vector2.zero
local p = Vector2.new(position.X, position.Y) - inset - canvas.AbsolutePosition
return p.X >= 0 and p.Y >= 0 and p.X <= canvas.AbsoluteSize.X and p.Y <= canvas.AbsoluteSize.Y, p
end
table.insert(connections, inputService.InputBegan:Connect(function(input)
if not frame.Visible or not gui.Parent or dragInput then return end
if input.UserInputType ~= Enum.UserInputType.MouseButton1 and input.UserInputType ~= Enum.UserInputType.Touch then return end
if not inside(input.Position) then return end
dragInput, dragStart, dragCenter, dragged = input, Vector2.new(input.Position.X, input.Position.Y), center, false
end))
table.insert(connections, inputService.InputChanged:Connect(function(input)
if not frame.Visible then return end
if input.UserInputType == Enum.UserInputType.MouseWheel then
local hit, p = inside(inputService:GetMouseLocation())
if hit then zoom(input.Position.Z > 0 and 1.3 or 1 / 1.3, p) end
elseif dragInput and (input == dragInput or (dragInput.UserInputType == Enum.UserInputType.MouseButton1 and input.UserInputType == Enum.UserInputType.MouseMovement)) then
local delta = Vector2.new(input.Position.X, input.Position.Y) - dragStart
if delta.Magnitude > 4 then dragged = true end
if dragged then
autoFitUntil = 0
center = dragCenter + Vector2.new(-delta.X, delta.Y) / pixelsPerStud
suppressClickUntil = os.clock() + 0.25
setFollow(false)
dirty = true
end
end
end))
table.insert(connections, inputService.InputEnded:Connect(function(input)
if input == dragInput then
if dragged then suppressClickUntil = os.clock() + 0.25 end
dragInput = nil
end
end))
layout()
table.insert(connections, RunService.Heartbeat:Connect(function()
if stopped or not gui.Parent or not frame.Visible then return end
layout()
local now = os.clock()
if now - lastRefresh < (dirty and 1 / 30 or C.MapRefreshSeconds) then return end
lastRefresh, dirty = now, false
render()
end))
end
installChestMap()
-- TRACERS & GOLD 100x100x100 HITBOX VISUALIZER
local traceParts = {}
if SHOW_ROUTE_TRACERS or SHOW_HITBOX_VISUALIZER then
local hitboxes = {}
local function getHitbox(index)
if hitboxes[index] then return hitboxes[index] end
local part = Instance.new("Part")
part.Name = "Hitbox100VisualizerPart"
part.Size, part.Transparency = HITBOX_SIZE, 1
part.Anchored = true -- Visual marker only; never anchors the character or boat.
part.CanCollide, part.CanTouch, part.CanQuery = false, false, false
part.Parent = workspace.Terrain
local outline = Instance.new("SelectionBox")
outline.Name = "Hitbox100GoldOutline"
outline.Color3 = Color3.fromRGB(255, 215, 0)
outline.LineThickness, outline.SurfaceTransparency = 0.25, 1
outline.Adornee, outline.Visible = part, false
outline.Parent = workspace.Terrain
local item = {part = part, outline = outline}
hitboxes[index] = item
table.insert(traceParts, outline)
table.insert(traceParts, part)
return item
end
local function makeTracer(name, color)
local from = Instance.new("Attachment", workspace.Terrain)
local dest = Instance.new("Attachment", workspace.Terrain)
local beam = Instance.new("Beam", workspace.Terrain)
beam.Name = name
beam.Attachment0, beam.Attachment1 = from, dest
beam.FaceCamera, beam.Segments = true, 1
beam.Width0, beam.Width1 = 0.35, 0.35
beam.Color, beam.Transparency = ColorSequence.new(color), NumberSequence.new(0.2)
beam.Enabled = false
table.insert(traceParts, beam)
table.insert(traceParts, from)
table.insert(traceParts, dest)
return {from = from, dest = dest, beam = beam}
end
local currentTrace = SHOW_ROUTE_TRACERS and makeTracer("FarmRouteCurrent", Color3.fromRGB(75, 215, 255))
local nextTrace = SHOW_ROUTE_TRACERS and makeTracer("FarmRouteNext", Color3.fromRGB(255, 210, 95))
local function updateTracer(tracer, from, dest)
if not tracer then return end
tracer.beam.Enabled = from ~= nil and dest ~= nil
if tracer.beam.Enabled then
tracer.from.WorldPosition, tracer.dest.WorldPosition = from, dest
end
end
table.insert(connections, RunService.RenderStepped:Connect(function()
local _, root = parts()
local count = 0
local function showHitbox(frame)
count += 1
local item = getHitbox(count)
if item.part.CFrame ~= frame then item.part.CFrame = frame end
item.outline.Visible = true
end
if not stopped and root and SHOW_HITBOX_VISUALIZER then
-- Draw each real chest in the pass, including cached geometry when unloaded.
for _, record in ipairs(currentTargetRecords or {}) do
local trigger = loadedTrigger(record)
local frame = trigger and trigger.CFrame or (record.geometry and record.geometry.cframe)
if frame then showHitbox(frame) end
end
if count == 0 and currentTargetBoxCenter then showHitbox(CFrame.new(currentTargetBoxCenter)) end
end
for index = count + 1, #hitboxes do hitboxes[index].outline.Visible = false end
local enabled = not stopped and root ~= nil
updateTracer(currentTrace, enabled and root.Position or nil, enabled and currentRouteDestination or nil)
updateTracer(nextTrace, enabled and currentTargetBoxCenter or nil, enabled and currentNextRoutePosition or nil)
end))
end
-- MAIN FARM LOOP
-- An immediately completed/rejected leg must not restart planning indefinitely in one frame.
local farmFrame = 0
table.insert(connections, RunService.Heartbeat:Connect(function() farmFrame += 1 end))
task.spawn(function()
local ok, err = xpcall(function()
display("Preparing chest locations…")
local startupDeadline = os.clock() + C.CharacterTimeout
while not stopped and (not initialScanComplete or not game:IsLoaded()) and os.clock() < startupDeadline do
RunService.Heartbeat:Wait()
end
if stopped then return end
refreshChests(true)
local startupBalance = readBeli()
if startupBalance then
lastPickupBalance = startupBalance
if startingBeli == nil then
startingBeli, moneyStarted = startupBalance, workspace:GetServerTimeNow()
end
end
if not initialScanComplete then log("Initial discovery still running; continuing with known spawns") end
local lastPlanningFrame = -1
while not stopped do
if farmFrame == lastPlanningFrame then RunService.Heartbeat:Wait() end
if stopped then break end
lastPlanningFrame = farmFrame
scanDealers()
refreshChests()
local _, root = waitCharacter(C.CharacterTimeout)
if stopped then break end
if not root then task.wait(0.5); continue end
-- Resolve Boat or seamless Foot mode
local boat, seat = getActiveVehicleOrCharacter()
local currentSpeed = boat and C.BoatSpeed or C.Speed
liveNavigation.speed = currentSpeed
if discovery.active then
local region = chooseDiscovery(root, currentSpeed)
if region then
discoverArea(boat, seat, region)
continue
end
end
local plan = choose(root, nil, currentSpeed)
if not plan then
liveNavigation.plan = nil
currentRouteDestination, currentTargetBoxCenter = nil, nil
currentTargetRecords, currentNextRoutePosition = nil, nil
display("Watching known chest respawns…")
pauseFlight()
task.wait(C.PollSeconds)
continue
end
local node = plan.node
currentNextRoutePosition = plan.route and plan.route[2] and plan.route[2].position or nil
display(string.format("%s · %s", boat and "Boat" or "Foot",
node.isCluster and ("Cluster (" .. node.clusterCount .. " chests)") or node.record.name))
-- Execute direct 3D flight (auto-adjusts speed and physics based on boat or foot)
local outcome = flyThroughTarget(boat, seat, node)
if outcome ~= "arrived" and outcome ~= "unavailable" and outcome ~= "interrupted" and outcome ~= "reroute" then
for _, record in ipairs(node.records or {node.record}) do
record.failures = (record.failures or 0) + 1
record.cooldown = workspace:GetServerTimeNow() + 10
end
end
end
end, debug.traceback)
stopped = true
pauseFlight()
if boatSeatCleanupConnection then boatSeatCleanupConnection:Disconnect() end
preparedBoat = nil
if persistentNoclipConn then persistentNoclipConn:Disconnect() end
restoreFlightCollision()
if persistentLinearVelocity then persistentLinearVelocity:Destroy() end
if persistentAttachment then persistentAttachment:Destroy() end
for _, conn in ipairs(connections) do conn:Disconnect() end
for _, part in ipairs(traceParts) do part:Destroy() end
for part, original in pairs(chestOriginals) do
if part.Parent then
pcall(function()
part.Size = original.size
part.CanCollide = original.canCollide
end)
end
end
if ok then
gui:Destroy()
else
titleLabel.Text = "Chest Farm · Error"
statusLabel.Text = "Stopped: check developer console"
statusLabel.TextColor3 = Color3.fromRGB(255, 130, 130)
end
if globalEnvironment.ChestFarmerBoatStop == stop then globalEnvironment.ChestFarmerBoatStop = nil end
if not ok then warn("[Chest Farmer] " .. tostring(err)) end
end)More for you

Steal An Egg
Lumin Hub | #1 | Working Auto Steal
- Insta Steal (Beta) - Auto Steal All - Auto Steal Selected - Global Auto Farm - Auto Return to Base - Auto Complete Index - Unequip After Index Hatch - Anti…
![Dracula HUB | Easy Key system — Roblox script for [OPE V2] Fruit Battlegrounds](https://c--5203ac31-0c19-435e-800e-18803c17ddbe-prod.lovable.cloud/storage/v1/object/sign/script-media/imports/945d723f-2a73-44af-959f-beb656d50c56/cover-3db6f6a0.png?token=eyJraWQiOiI2ODI1YTFmMS1jYjM3LTRlOTUtYjk5OC0xMDg0YzBjMzlkN2UiLCJhbGciOiJIUzUxMiJ9.eyJ1cmwiOiJzY3JpcHQtbWVkaWEvaW1wb3J0cy85NDVkNzIzZi0yYTczLTQ0YWYtOTU5Zi1iZWI2NTZkNTBjNTYvY292ZXItM2RiNmY2YTAucG5nIiwic2NvcGUiOiJkb3dubG9hZCIsImlhdCI6MTc5MTIwOTM0NSwiZXhwIjoxNzkxMjEyOTQ1fQ.gXyasMnhdIRvxrd2TRSZqDJhL_uU3a8J381G6KSSKXt4qHq0oacRCVtNn0Z9ohXxNfH_Ytm-dtxK9DW4Zu5OUw)
[OPE V2] Fruit Battlegrounds
Dracula HUB | Easy Key system
• Auto Farm Fruit • Auto Farm Boss • Auto Boss Retreat • Auto Boss Hop • Auto Spin Fruits (Best) • Auto Respawn • Auto-Kill on Low Stamina • Auto Teleport in…

Universal Hub
Airflow HUB
this hub supports these games: Murder Mystery 2 (MM2) Animal Hospital anime dice illegal soccer sell ores fish it volleyball legends tower of hell Grow a…