Run it
Copy the script and paste it into your executor.
(() (:())(, , ) )
SPEED =
SPEED_MIN =
SPEED_MAX =
SPEED_PERIOD =
EFFECTIVE_AVG_SPEED = (SPEED_MAX + SPEED_MIN) *
BOAT_PURCHASE_RANGE =
BOAT_APPROACH_RANGE =
MIN_ROOT_Y =
MAX_TRAVEL_SECONDS =
LOAD_UI =
SHOW_ROUTE_TRACERS =
SHOW_HITBOX_VISUALIZER =
REWARD_SEA =
ESTIMATED_PICKUP_SECONDS =
LOOKAHEAD_STOPS =
MAP_OUTLIER_DISTANCE =
DISCOVERY_RUN =
DISCOVERY_RADIUS =
STREAM_TIMEOUT =
HITBOX_SIZE = .(, , )
HITBOX_HALF_EXTENT =
Players = :()
RunService = :()
ReplicatedStorage = :()
player = Players.LocalPlayer
player
.()
player = Players.LocalPlayer
()
(serverTime)
mid = (SPEED_MAX + SPEED_MIN) *
amp = (SPEED_MAX - SPEED_MIN) *
omega = ( * .pi) / SPEED_PERIOD
serverTimeCycle = serverTime % SPEED_PERIOD
mid + amp * .(serverTimeCycle * omega)
C = {
Speed = SPEED,
BoatSpeed = EFFECTIVE_AVG_SPEED,
MinRootY = MIN_ROOT_Y,
PollSeconds = ,
SweepMargin = ,
MinimumTouchDepth = ,
ArrivalDistance = ,
PendingConfirmSeconds = ,
CharacterTimeout = ,
ChestFailureCooldown = ,
MaxChestCooldown = ,
MatchRadius = ,
ObserveSeconds = ,
ReplanSeconds = ,
SwitchGain = ,
MinimumCommitSeconds = ,
FinishDistance = ,
BeamWidth = ,
BranchWidth = ,
PlanBudgetSeconds = ,
MapRefreshSeconds = ,
Debug = ,
}
gradeBySpawnName = {Chest1 = , Chest2 = , Chest3 = }
chestEconomy = {
Silver = {respawn = , rewards = {{, }, {, }, {, }}},
Gold = {respawn = , rewards = {{, }, {, }, {, }}},
Diamond = {respawn = , rewards = {{, }, {, }, {, }}},
}
(record) gradeBySpawnName[record.name]
(record) chestEconomy[(record)]
(record) record.respawnEstimate (gradeBySpawnName[record.name] (record).respawn)
(position)
position.Y >= C.MinRootY position
.(position.X, C.MinRootY, position.Z)
legHistory = {}
maxLegHistory =
avgLegSpeed =
legHistoryMode =
measuredMotion = {}
(distance, timeTaken, mode)
timeTaken <= distance <=
legHistoryMode ~= mode
.(legHistory)
legHistoryMode = mode
.(legHistory, {distance = distance, time = timeTaken})
#legHistory > maxLegHistory
.(legHistory, )
totalDistance, totalTime = ,
_, leg (legHistory)
totalDistance += leg.distance
totalTime += leg.time
avgLegSpeed = totalDistance / totalTime
measuredMotion[mode] = {speed = avgLegSpeed, samples = #legHistory}
Planner = {}
Planner.(a, b, speed3D)
dist3D = (b - a).Magnitude
mode = speed3D == C.Speed
observed = measuredMotion[mode]
calibrated = speed3D
observed observed.samples >=
calibrated = .(observed.speed, speed3D * , speed3D * )
dist3D / calibrated
Planner.(node, fromPosition, margin)
center = (node.position)
half = node.halfSize .(HITBOX_HALF_EXTENT, HITBOX_HALF_EXTENT, HITBOX_HALF_EXTENT)
entryPoint = .(
.(fromPosition.X, center.X - half.X, center.X + half.X),
.(fromPosition.Y, center.Y - half.Y, center.Y + half.Y),
.(fromPosition.Z, center.Z - half.Z, center.Z + half.Z))
inward = center - entryPoint
direction = inward.Magnitude > inward.Unit .(, , -)
exitPoint = entryPoint + direction * (margin + )
depth = C.MinimumTouchDepth + C.ArrivalDistance
inset = .(.(depth, half.X), .(depth, half.Y), .(depth, half.Z))
exitPoint = .(
.(exitPoint.X, center.X - half.X + inset.X, center.X + half.X - inset.X),
.(exitPoint.Y, center.Y - half.Y + inset.Y, center.Y + half.Y - inset.Y),
.(exitPoint.Z, center.Z - half.Z + inset.Z, center.Z + half.Z - inset.Z))
(entryPoint), center, (exitPoint)
Planner.(position, node, startAt, now, options)
entry, _, exit = Planner.(node, position, options.sweepMargin)
travel = options.travelEstimator options.(position, entry)
Planner.(position, entry, options.speed)
travel > options.maxTravel
node.readyAt node.readyAt > startAt + travel
sweepSeconds = options.(entry, exit)
{seconds = .(, travel + sweepSeconds + options.service),
probability = node.reliability, exitPosition = exit}
(a, b)
.(a.score - b.score) > a.score > b.score
.(a.elapsed - b.elapsed) > a.elapsed < b.elapsed
a.first.id < b.first.id
(list, entry, limit)
index = #list +
i, old (list) (entry, old) index = i;
index <= limit
.(list, index, entry)
#list > limit .(list)
Planner.(position, nodes, now, options, forcedFirstId)
beam = {{position = position, elapsed = , reward = , visited = {}, route = {}}}
best
deadline = options.budget (.() + options.budget)
roots = {}
_, node (nodes)
forcedFirstId node.id == forcedFirstId
leg = Planner.(position, node, now, now, options)
leg
reward = node.value * leg.probability
(roots, {position = leg.exitPosition, first = node, elapsed = leg.seconds,
reward = reward, score = reward / (leg.seconds + options.smoothing),
visited = {[node.id] = }, route = {node}}, options.width)
#roots ==
beam, best = roots, roots[]
depth = , options.depth
expanded = {}
_, state (beam)
depth > deadline .() >= deadline best
branches = {}
exhausted =
nodeIndex, node (nodes)
state.visited[node.id] (depth > forcedFirstId node.id == forcedFirstId)
leg = Planner.(state.position, node, now + state.elapsed, now, options)
leg
elapsed = state.elapsed + leg.seconds
reward = state.reward + node.value * leg.probability
entry = {
position = leg.exitPosition, first = state.first node,
elapsed = elapsed, reward = reward,
score = reward / (elapsed + options.smoothing),
parent = state, node = node,
}
(branches, entry, options.branch)
nodeIndex % == deadline .() >= deadline
exhausted =
_, entry (branches)
entry.visited = .(entry.parent.visited)
entry.visited[entry.node.id] =
entry.route = .(entry.parent.route)
.(entry.route, entry.node)
entry.parent, entry.node = ,
(expanded, entry, options.width)
best (entry, best) best = entry
exhausted best
#expanded ==
beam = expanded
best
dealerList, lastDealerScan = {}, -.huge
ownedBoat =
(npc)
(npc:() npc:())
npc.Name:():(, ):(, , )
folder = :()
folder npc:(folder)
position = npc:() npc:().Position npc.Position
_, dealer (dealerList)
(dealer.position - position).Magnitude <=
dealer.instance, dealer.position, dealer.name = npc, position, npc.Name
.(dealerList, {instance = npc, position = position, name = npc.Name})
(force)
now = :()
force now - lastDealerScan <
lastDealerScan = now
i = #dealerList, , -
dealer = dealerList[i]
dealer.instance dealer.instance:()
dealer.instance =
(boat)
boat boat.Parent
seat = boat:(, )
seat seat:() seat
(boat)
seat = (boat)
seat seat.Occupant seat.Occupant.Parent == player.Character
owner = boat:(, )
owner owner:()
value = owner.Value
value == player value == player.Name value == player.UserId
(value) == (player.UserId)
()
char = player.Character
root = char char:()
hum = char char:()
char char:() root hum hum.Health >
char, root, hum
()
char, root, hum = ()
char root
hum hum.SeatPart hum.SeatPart:()
motionPart = hum.SeatPart.AssemblyRootPart hum.SeatPart
vel = motionPart.AssemblyLinearVelocity motionPart.Velocity
vel.Magnitude
vel = root.AssemblyLinearVelocity root.Velocity
vel.Magnitude
playerGui = player:()
GUI_NAME =
globalEnvironment = ()
globalEnvironment.ChestFarmerBoatStop (globalEnvironment.ChestFarmerBoatStop)
oldGui = playerGui playerGui:(GUI_NAME)
oldGui oldGui:()
gui = .()
gui.Name, gui.ResetOnSpawn = GUI_NAME,
LOAD_UI
playerGui
gui.Parent = playerGui
.(()
latePlayerGui = player:()
gui.Parent gui.Parent = latePlayerGui
)
panel = .()
panel.Size = .(, )
panel.Position = .(, )
panel.BackgroundColor3 = .(, , )
panel.BorderSizePixel =
panel.Parent = gui
corner = .()
corner.CornerRadius = .(, )
corner.Parent = panel
panelScale = .()
panelScale.Parent = panel
(text, x, y, width, height, size, color)
item = .()
item.BackgroundTransparency =
item.Position = .(x, y)
item.Size = .(width, height)
item.Font = .Font.Gotham
item.TextSize = size
item.TextColor3 = color
item.TextXAlignment = .TextXAlignment.Left
item.TextTruncate = .TextTruncate.AtEnd
item.Text = text
item.Parent = panel
item
light = .(, , )
muted = .(, , )
titleLabel = (, , , , , , light)
(, , , , , , muted)
(, , , , , , muted)
gainedLabel = (, , , , , , .(, , ))
rateLabel = (, , , , , , light)
(, , , , , , muted)
(, , , , , , muted)
speedLabel = (, , , , , , .(, , ))
avgSpeedLabel = (, , , , , , .(, , ))
nextPassLabel = (, , , , , , light)
availabilityLabel = (, , , , , , muted)
plannerLabel = (, , , , , , muted)
statusLabel = (, , , , , , muted)
updateSmallDetails
stopButton = .()
stopButton.Size = .(, )
stopButton.Position = .(, )
stopButton.Text =
stopButton.Font = .Font.Gotham
stopButton.TextSize =
stopButton.TextColor3 = light
stopButton.BackgroundColor3 = .(, , )
stopButton.BorderSizePixel =
stopButton.Parent = panel
buttonCorner = .()
buttonCorner.CornerRadius = .(, )
buttonCorner.Parent = stopButton
mapButton = .()
mapButton.Size = .(, )
mapButton.Position = .(, )
mapButton.Text =
mapButton.Font = .Font.Gotham
mapButton.TextSize =
mapButton.TextColor3 = light
mapButton.BackgroundColor3 = .(, , )
mapButton.BorderSizePixel =
mapButton.Parent = panel
mapButtonCorner = .()
mapButtonCorner.CornerRadius = .(, )
mapButtonCorner.Parent = mapButton
stopped =
connections = {}
uiInput = :()
uiLastViewport = .zero
uiLastTouch =
uiPanelPosition
(position)
camera = .CurrentCamera
camera
topLeft, bottomRight = :():()
usable = camera.ViewportSize - topLeft - bottomRight
size = .(panel.Size.X.Offset, panel.Size.Y.Offset) * panelScale.Scale
uiPanelPosition = .(
.(position.X, , .(, usable.X - size.X)),
.(position.Y, , .(, usable.Y - size.Y)))
panel.Position = .(uiPanelPosition.X, uiPanelPosition.Y)
()
camera = .CurrentCamera
camera
viewport = camera.ViewportSize
touch = uiInput.TouchEnabled
viewport == uiLastViewport touch == uiLastTouch
uiLastViewport, uiLastTouch = viewport, touch
topLeft, bottomRight = :():()
usable = viewport - topLeft - bottomRight
panelScale.Scale = .(, .(, (usable.X - ) / ))
panel.Size = .(, touch )
(uiPanelPosition .(touch , touch .(, .(, usable.Y - ))))
stopButton.Size = .(, touch )
mapButton.Size = .(, touch )
stopButton.Position = .(, touch )
mapButton.Position = .(, touch )
_, child (panel:())
child:()
originalY = child:()
originalY originalY = child.Position.Y.Offset; child:(, originalY)
child.Position = .(child.Position.X.Offset, originalY + (touch originalY >= ))
()
dragHandle = .()
dragHandle.Name =
dragHandle.BackgroundTransparency =
dragHandle.Size = .(, )
dragHandle.Active =
dragHandle.ZIndex =
dragHandle.Parent = panel
statsDragInput, statsDragStart, statsDragPosition
.(connections, dragHandle.InputBegan:((input)
stopped statsDragInput
input.UserInputType ~= .UserInputType.MouseButton1
input.UserInputType ~= .UserInputType.Touch
statsDragInput = input
statsDragStart = .(input.Position.X, input.Position.Y)
statsDragPosition = .(panel.Position.X.Offset, panel.Position.Y.Offset)
))
.(connections, uiInput.InputChanged:((input)
statsDragInput stopped panel.Visible
input == statsDragInput (statsDragInput.UserInputType == .UserInputType.MouseButton1
input.UserInputType == .UserInputType.MouseMovement)
position = .(input.Position.X, input.Position.Y)
(statsDragPosition + position - statsDragStart)
))
.(connections, uiInput.InputEnded:((input)
input == statsDragInput statsDragInput =
))
virtualUser = :()
antiAfkConnection = player.Idled:(()
virtualUser:()
virtualUser:(.())
)
.(connections, antiAfkConnection)
candidates, records = {}, {}
chestOriginals = ({}, {__mode = })
currentRouteDestination
currentTargetBoxCenter =
currentTargetRecords =
currentNextRoutePosition =
choose, eligible, observeRecord
liveNavigation = {plan = , nodeCount = , planMilliseconds = , speed = C.BoatSpeed}
discovery = {active = DISCOVERY_RUN, regions = {}, completed = , skipped = ,
seededRecords = {}, lastSeedScan = -.huge}
streamingJob
(position)
.StreamingEnabled stopped
streamingJob streamingJob.done
(streamingJob.position - position).Magnitude <= DISCOVERY_RADIUS streamingJob
job = {position = position, done = }
streamingJob = job
.(()
job.ok = (() player:(position, STREAM_TIMEOUT) )
job.done =
)
job
lastObserved = -.huge
(message)
C.Debug ( .. message)
(message)
gui.Parent statusLabel.Text = message
startingBeli, moneyStarted
(value)
rounded = .(.(value) + )
digits = .(, rounded)
grouped = digits:():(, ):():(, )
(value < rounded > ) .. grouped
()
data = player:()
value = data data:()
value (value:() value:()) value.Value
()
gui.Parent
balance = ()
balance
now = :()
startingBeli == startingBeli, moneyStarted = balance, now
gained = balance - startingBeli
elapsed = now - moneyStarted
gainedLabel.Text = (gained)
rateLabel.Text = (elapsed > gained * / elapsed )
moneyRefreshAt =
.(connections, RunService.Heartbeat:(()
gui.Parent
()
velocityText = .(, ())
speedLabel.Text ~= velocityText speedLabel.Text = velocityText
now = .()
now < moneyRefreshAt
moneyRefreshAt = now +
()
updateSmallDetails ()
avgLegSpeed >
avgSpeedLabel.Text = .(, avgLegSpeed)
avgSpeedLabel.Text =
))
()
stopped
stopped =
()
globalEnvironment.ChestFarmerBoatStop = stop
.(connections, stopButton.Activated:(stop))
.(connections, gui.Destroying:(stop))
(timeout)
deadline = :() + timeout
char, root, hum = ()
char char, root, hum
.(C.PollSeconds)
stopped :() >= deadline
(part)
part part:() part.CanTouch ==
(record)
trigger = record.spawnPart record.part
trigger trigger:() trigger
(record, now)
trigger = (record)
trigger trigger.CanTouch now .huge
record.geometry record.lastCanTouch == .huge
record.lastCanTouch now
record.readyAt .huge
(record, now)
trigger = (record)
trigger trigger.CanTouch
trigger (record, now) <= now
record.readyAt record.readyAt < .huge record.readyAt > now
record.lastCanTouch ==
(part)
stopped part:()
(()
part.Size ~= HITBOX_SIZE part.Size = HITBOX_SIZE
part.CanCollide part.CanCollide =
)
(obj)
(obj)
obj:() obj.Name:():(, , )
visualFolder = :()
visualFolder obj:(visualFolder)
chestOriginals[obj]
chestOriginals[obj] = {size = obj.Size, canCollide = obj.CanCollide}
_, property ({, })
.(connections, obj:(property):(()
(obj)
))
.(connections, obj:():(()
stopped obj:()
record = candidates[obj]
(record) ~=
attempt = record.pendingAttempt
obj.CanTouch attempt attempt.done attempt.activeBefore attempt.crossed
attempt.touchPart == obj
attempt.deactivatedAt = :()
observeRecord (record, obj, :())
))
(obj)
candidates[obj] == candidates[obj] =
.(connections, .DescendantAdded:(track))
initialScanComplete =
.(()
pending = {}
stopped #pending >
_ = ,
item = .(pending)
item
(item)
_, child (item:()) .(pending, child)
.()
initialScanComplete = stopped
)
(record, now, ours)
record.state == record.emptyAt now - record.emptyAt <
ours record.lastLossCounted
record.otherLosses = .(, (record.otherLosses ) - )
record.lastLossCounted =
record.emptyAt = now
record.readyAt = now + ((record) (record).respawn)
record.observationGap =
record.state =
record.lastLossCounted = ours
ours record.otherLosses = (record.otherLosses ) +
observeRecord = (record, trigger, now)
trigger trigger:()
record.loaded, record.observationGap = ,
priorTouch = record.lastCanTouch
gap = record.observationGap
record.spawnPart = trigger
record.loaded =
record.geometry record.geometry.cframe ~= trigger.CFrame record.geometry.size ~= trigger.Size
record.geometry = {cframe = trigger.CFrame, size = trigger.Size}
record.position, record.lastObservedAt = trigger.Position, now
trigger.CanTouch
priorTouch == record.emptyAt gap
measured = now - record.emptyAt
nominal = (record).respawn
measured > nominal * measured < nominal *
record.respawnEstimate = (record.respawnEstimate nominal) * + measured *
record.part, record.state, record.collected = trigger, ,
record.emptyAt, record.readyAt = , now
record.initiallyEmptyAt =
record.part =
priorTouch ==
attempt = record.pendingAttempt
(record, now, attempt attempt.deactivatedAt ~= )
record.state =
record.emptyAt record.initiallyEmptyAt
record.initiallyEmptyAt = now
record.readyAt = now + ((record) (record).respawn)
record.lastCanTouch, record.observationGap = trigger.CanTouch,
pendingAttempts = {}
startupMissReports =
lastPickupBalance = ()
(record, sweepSeconds)
record.pendingAttempt record.pendingAttempt
now = :()
trigger = record.spawnPart record.part
(trigger)
attempt = {record = record, touchPart = trigger, activeBefore = (trigger) == ,
expires = now + sweepSeconds + C.PendingConfirmSeconds + , crossed = }
record.pendingAttempt = attempt
record.pendingUntil = attempt.expires
.(pendingAttempts, attempt)
attempt
(attempt, now)
attempt.done
attempt.done =
record = attempt.record
(record, now, )
record.collected =
record.successes = (record.successes ) +
record.failures =
record.cooldown = now +
.(connections, RunService.Heartbeat:(()
now, balance = :(), ()
balance lastPickupBalance balance > lastPickupBalance
gain = balance - lastPickupBalance
_, attempt (pendingAttempts)
attempt.done attempt.crossed now <= attempt.expires
attempt.beliEvidence = (attempt.beliEvidence ) + gain
balance lastPickupBalance = balance
i = #pendingAttempts, , -
attempt = pendingAttempts[i]
observedPart = attempt.touchPart
attempt.done attempt.crossed attempt.activeBefore now <= attempt.expires
(attempt.beliEvidence ) >
(attempt.deactivatedAt (observedPart observedPart:() observedPart.CanTouch == ))
(attempt, attempt.deactivatedAt now)
attempt.done now >= attempt.expires
record = attempt.record
record.pendingAttempt == attempt
record.pendingAttempt, record.pendingUntil = ,
attempt.done attempt.crossed attempt.activeBefore
observedPart observedPart:() observedPart.CanTouch
startupMissReports <
startupMissReports +=
char, root, hum = ()
touchParts, anchoredParts = ,
char
_, part (char:())
part:()
part.CanTouch touchParts +=
part.Anchored anchoredParts +=
trigger = record.part record.spawnPart
(.(,
startupMissReports, record.name, ((trigger) == ),
(trigger trigger.CanTouch), touchParts, anchoredParts,
(hum hum.SeatPart ~= ), (initialScanComplete)))
record.misses = (record.misses ) +
record.failures = (record.failures ) +
record.cooldown = now + .(C.MaxChestCooldown, C.ChestFailureCooldown * ^ .(record.failures - , ))
.(pendingAttempts, i)
))
(force)
now = :()
force now - lastObserved < C.ObserveSeconds
observedSeconds = .(, .(, now - lastObserved))
lastObserved = now
_, r (records) r.spawnPart = ; r.part =
part (candidates)
part:()
candidates[part] =
(part)
r = candidates[part]
r ==
r =
_, existing (records)
existing.name == part.Name (existing.position - part.Position).Magnitude <= C.MatchRadius
r = existing
r
r = {id = #records + , name = part.Name, position = part.Position,
cooldown = , failures = , successes = , misses = ,
exposure = , otherLosses = , state = ,
readyAt = .huge}
.(records, r)
candidates[part] = r
r.spawnPart = part
(part) r.part = part
r.position = part.Position
_, r (records)
r.state == r.exposure = (r.exposure ) + observedSeconds
(r, r.spawnPart, now)
(target, stopRadius)
char, root, hum = ()
char
target = (target)
previousFlight = root:()
flightWasEnabled = previousFlight previousFlight.Enabled
previousFlight previousFlight.Enabled =
attachment = .(, root)
drive = .(, root)
drive.Attachment0 = attachment
drive.RelativeTo = .ActuatorRelativeTo.World
drive.ForceLimitsEnabled =
originals = {}
(part)
part:()
originals[part] == originals[part] = part.CanCollide
part.CanCollide =
_, part (char:()) (part)
added = char.DescendantAdded:(disableCollision)
noclipConn = RunService.PreSimulation:(()
part (originals)
part.Parent part.CanCollide part.CanCollide =
)
estimate = Planner.(root.Position, target, C.Speed)
began = :()
arrived =
stopped player.Character == char hum.Health > :() - began <= estimate * +
RunService.Heartbeat:()
delta = target - root.Position
delta.Magnitude <= stopRadius arrived = ;
drive.VectorVelocity = delta.Unit * C.Speed
noclipConn:()
added:()
part, canCollide (originals)
part.Parent part.CanCollide = canCollide
drive:()
attachment:()
previousFlight previousFlight.Parent
previousFlight.Enabled = flightWasEnabled
arrived
preparedBoat, boatSeatCleanupConnection
(boat)
boat boat.Parent preparedBoat == boat
boatSeatCleanupConnection boatSeatCleanupConnection:()
preparedBoat = boat
(part)
part:() (part:() part.Name ~= )
part:()
boatSeatCleanupConnection = boat.DescendantAdded:((part)
stopped (part)
)
_, part (boat:()) (part)
()
boats = :() :(, )
remoteFolder = ReplicatedStorage:()
event = remoteFolder remoteFolder:()
boats event
_, root = ()
_, existing (boats:())
seat = (existing)
seat root (existing) (root.Position - seat.Position).Magnitude <=
(existing)
existing
seen = {}
_, child (boats:()) seen[child] =
arrivals = {}
added = boats.ChildAdded:((child) .(arrivals, child) )
.(() (() event:(, ) ) )
deadline = :() +
found
_, boat (arrivals)
boat.Parent == boats seen[boat] (boat) (boat)
found = boat
found
.()
stopped :() >= deadline
added:()
found (found)
found
(boat)
(boat)
char, root, hum = ()
seat = (boat)
char seat
seat:(hum)
deadline = :() +
stopped :() < deadline seat.Occupant ~= hum .()
seat.Occupant == hum
()
char, root, hum = ()
char ,
hum.SeatPart hum.SeatPart:()
boat = hum.SeatPart:()
boat
ownedBoat = boat
(boat)
seat = (boat)
seat seat.Occupant == hum
titleLabel.Text =
boat, seat
ownedBoat ownedBoat.Parent
(ownedBoat)
seat = (ownedBoat)
seat (root.Position - seat.Position).Magnitude <=
()
(seat.Position + .(, , ), )
(ownedBoat)
titleLabel.Text =
ownedBoat, seat
()
nearestDealer, nearestDist = , .huge
_, dealer (dealerList)
dist = (root.Position - dealer.position).Magnitude
dist < nearestDist
nearestDealer, nearestDist = dealer, dist
nearestDealer nearestDist <=
()
(root.Position - nearestDealer.position).Magnitude > BOAT_APPROACH_RANGE
(nearestDealer.position, BOAT_APPROACH_RANGE)
boat = ()
boat
ownedBoat = boat
seat = (boat)
seat
(seat.Position + .(, , ), )
(boat)
titleLabel.Text =
boat, seat
titleLabel.Text =
,
persistentLinearVelocity =
persistentAttachment =
persistentNoclipConn =
noclipChar, noclipBoat = ,
noclipOriginals = {}
noclipAdded = {}
()
_, connection (noclipAdded) connection:()
.(noclipAdded)
part, canCollide (noclipOriginals)
part.Parent part.CanCollide = canCollide
.(noclipOriginals)
noclipChar, noclipBoat = ,
(char, boat, motionPart)
char == noclipChar boat == noclipBoat
()
noclipChar, noclipBoat = char, boat
(part)
part:()
noclipOriginals[part] == noclipOriginals[part] = part.CanCollide
part.CanCollide =
(container)
container
_, part (container:()) (part)
.(noclipAdded, container.DescendantAdded:(disable))
(char)
(boat)
motionPart
(motionPart)
ok, connected = (() motionPart:() )
ok _, part (connected) (part)
persistentNoclipConn
persistentNoclipConn = RunService.PreSimulation:(()
part (noclipOriginals)
part.Parent
noclipOriginals[part] =
part.CanCollide
part.CanCollide =
)
activeFlightCommand
(command, now)
motionPart, lv, dir = command.part, command.constraint, command.direction
stopped motionPart.Parent lv.Parent
speed = command.isBoat .((now), SPEED_MIN, SPEED_MAX) C.Speed
velocity = dir * speed
command.seat command.seat.Parent
command.seat.ThrottleFloat =
command.seat.SteerFloat =
up = .(dir.Y) > .(, , -) .yAxis
motionPart.CFrame = .(motionPart.Position, motionPart.Position + dir, up)
motionPart.AssemblyAngularVelocity = .zero
lv.VectorVelocity = velocity
motionPart.AssemblyLinearVelocity = velocity
.(connections, RunService.PreSimulation:(()
command = activeFlightCommand
command
command.character ~= player.Character command.part.Parent command.constraint.Parent
activeFlightCommand =
(command, :())
))
(boat, seat)
char, root = ()
motionPart = seat (seat.AssemblyRootPart seat) root
motionPart ,
persistentLinearVelocity persistentLinearVelocity.Parent ~= motionPart
persistentLinearVelocity persistentLinearVelocity:()
persistentAttachment persistentAttachment:()
persistentAttachment = .()
persistentAttachment.Name =
persistentAttachment.Parent = motionPart
persistentLinearVelocity = .()
persistentLinearVelocity.Name =
persistentLinearVelocity.Attachment0 = persistentAttachment
persistentLinearVelocity.RelativeTo = .ActuatorRelativeTo.World
persistentLinearVelocity.ForceLimitsEnabled =
persistentLinearVelocity.MaxForce = .huge
persistentLinearVelocity.VectorVelocity = .zero
persistentLinearVelocity.Parent = motionPart
(char, boat, motionPart)
persistentLinearVelocity, motionPart
()
activeFlightCommand =
persistentLinearVelocity persistentLinearVelocity.Parent
persistentLinearVelocity.VectorVelocity = .zero
motionPart = persistentLinearVelocity.Parent
motionPart:()
motionPart.AssemblyLinearVelocity = .zero
motionPart.AssemblyAngularVelocity = .zero
(boat, seat, destination, recordsToArm, guard)
char, root, hum = ()
char
lv, motionPart = (boat, seat)
lv motionPart
began = :()
startPos = root.Position
delta = destination - startPos
totalDist = delta.Magnitude
(position)
recordsToArm
_, rec (recordsToArm)
trigger = rec.spawnPart rec.part
offset = trigger trigger.CFrame:(position)
half = trigger trigger.Size *
(trigger) .(offset.X) <= half.X +
.(offset.Y) <= half.Y + .(offset.Z) <= half.Z +
attempt = (rec, )
attempt .(offset.X) <= half.X .(offset.Y) <= half.Y
.(offset.Z) <= half.Z attempt.crossed =
(startPos)
totalDist <= C.ArrivalDistance
initialDir = delta.Unit
isBoat = (boat ~= seat ~= )
minSpeed = isBoat SPEED_MIN C.Speed
timeout = (totalDist / minSpeed) +
outcome =
movingDistance, movingTime = ,
previousPosition, previousTime = motionPart.Position, .()
command = {part = motionPart, constraint = lv, direction = initialDir,
seat = seat, isBoat = isBoat, character = char}
(dir, now)
command.direction = dir
activeFlightCommand = command
(command, now)
(initialDir, began)
stopped player.Character == char hum.Health >
RunService.Heartbeat:()
frameTime = .()
framePosition = motionPart.Position
movingDistance += (framePosition - previousPosition).Magnitude
movingTime += frameTime - previousTime
previousPosition, previousTime = framePosition, frameTime
isBoat seat.Occupant ~= hum
seat:(hum)
seat.Occupant ~= hum outcome = ;
now = :()
now - began > timeout outcome = ;
currentPos = root.Position
currentDelta = destination - currentPos
currentDist = currentDelta.Magnitude
(currentPos)
guard
decision = (now, currentPos, currentDist)
decision outcome = decision;
passed = (currentPos - startPos):(initialDir) >= totalDist
currentDist <= C.ArrivalDistance passed
outcome =
(initialDir, now)
stopped player.Character ~= char hum.Health <=
outcome =
outcome ==
(movingDistance, movingTime, isBoat )
outcome == outcome ==
()
outcome
(boat, seat, node)
char, root = ()
char
recordsList = node.records
entryPoint, centerPoint, exitPoint = Planner.(node, root.Position, C.SweepMargin)
currentTargetBoxCenter, currentTargetRecords = centerPoint, recordsList
(outcome)
currentRouteDestination, currentTargetBoxCenter = ,
currentTargetRecords, currentNextRoutePosition = ,
outcome
()
_, record (recordsList)
(record.spawnPart record.part)
()
_, record (recordsList) (record)
(now, seconds)
_, record (recordsList)
(record, now) <= now + seconds
approachSeconds = Planner.(root.Position, entryPoint, liveNavigation.speed)
(:(), approachSeconds) ()
verificationJob
began, lastReplan = :(), :()
targetName = node.isCluster ( .. #recordsList .. ) node.record.name
(now, position, remaining)
(now, Planner.(position, entryPoint, liveNavigation.speed))
() verificationJob remaining <= liveNavigation.speed * STREAM_TIMEOUT + DISCOVERY_RADIUS
verificationJob = (centerPoint)
remaining <= C.FinishDistance now - began < C.MinimumCommitSeconds
now - lastReplan < C.ReplanSeconds
_, record (recordsList)
record.pendingAttempt
lastReplan = now
()
_, currentRoot = ()
currentRoot
best = (currentRoot, , liveNavigation.speed)
best
sameTarget = best.first.id == node.id
retained = sameTarget best (currentRoot, node.record, liveNavigation.speed)
sameTarget ( retained best.score > retained.score * C.SwitchGain)
retained
liveNavigation.plan = retained
currentNextRoutePosition = retained.route[] retained.route[].position
( .. targetName)
currentRouteDestination = entryPoint
approach = (boat, seat, entryPoint, recordsList, guard)
approach ~= (approach)
()
() ()
.StreamingEnabled
verificationJob = verificationJob (centerPoint)
()
deadline = :() + STREAM_TIMEOUT
stopped () :() < deadline
RunService.Heartbeat:()
()
allLoaded =
_, record (recordsList) (record) allLoaded = ;
allLoaded
verificationJob verificationJob = (centerPoint)
()
stopped ()
()
_, record (recordsList)
(record) record.cooldown = :() + C.ChestFailureCooldown
()
( .. targetName)
currentRouteDestination = exitPoint
((boat, seat, exitPoint, recordsList))
eligible = (record, now)
pending = record.pendingAttempt
(record, now) < .huge
(pending pending.done)
now >= (record.cooldown )
(record)
geometry = record.geometry
geometry.low geometry.low, geometry.high
half = geometry.size *
rotation = geometry.cframe
right, up, look = rotation.RightVector, rotation.UpVector, rotation.LookVector
radius = .(
half.X / (.(right.X) + .(right.Y) + .(right.Z)),
half.Y / (.(up.X) + .(up.Y) + .(up.Z)),
half.Z / (.(look.X) + .(look.Y) + .(look.Z)))
extent = .(radius, radius, radius)
low, high = rotation.Position - extent, rotation.Position + extent
low = .(low.X, .(low.Y, C.MinRootY), low.Z)
geometry.low, geometry.high = low, high
low, high
(aLow, aHigh, bLow, bHigh)
low = .(.(aLow.X, bLow.X), .(aLow.Y, bLow.Y), .(aLow.Z, bLow.Z))
high = .(.(aHigh.X, bHigh.X), .(aHigh.Y, bHigh.Y), .(aHigh.Z, bHigh.Z))
low, high
(rawNodes)
nodes, used = {}, {}
index, anchor (rawNodes)
used[index]
group, low, high = {anchor.record}, anchor.low, anchor.high
value, expected, readyAt = anchor.value, anchor.value * anchor.reliability, anchor.readyAt
used[index] =
other = index + , #rawNodes
used[other]
candidate = rawNodes[other]
anchor.inferred ~= candidate.inferred .(readyAt - candidate.readyAt) >
candidate.low.X > high.X - candidate.high.X < low.X +
candidate.low.Y > high.Y - candidate.high.Y < low.Y +
candidate.low.Z > high.Z - candidate.high.Z < low.Z +
nextLow, nextHigh = (low, high, candidate.low, candidate.high)
span = nextHigh - nextLow
.(span.X, span.Y, span.Z) >=
low, high = nextLow, nextHigh
value += candidate.value
expected += candidate.value * candidate.reliability
readyAt = .(readyAt, candidate.readyAt)
.(group, candidate.record)
used[other] =
.(nodes, {id = anchor.record.id, record = anchor.record, records = group,
position = (low + high) * , halfSize = (high - low) * ,
value = value, reliability = expected / value,
readyAt = readyAt, inferred = anchor.inferred,
isCluster = #group > , clusterCount = #group})
nodes
(now)
raw = {}
_, record (records)
(record, now)
low, high = (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)Loads code from the internet. It downloads more code when it runs (loadstring + HttpGet), which can change after it was posted. From: scriptblox.com.
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.