-- [[ Rscripts Risk Notice ]] -- This script is not verified by rscripts.net. Deal with caution. -- -- Stay safe: -- • Never log in on unofficial Roblox sites or lookalike domains. -- • Real Roblox links use roblox.com (check the .com ending). -- • Treat fake Roblox login / "claim reward" pages as phishing. -- [[ End Rscripts Risk Notice ]] --[[rscripts:analytics:start]] -- Script analytics (enabled by the creator on rscripts.net). -- Runs in its own thread and cannot affect the script below. task.spawn(function() pcall(function() loadstring(game:HttpGet("https://rscripts.net/api/telemetry/v2/client.lua?s=6ada805377c260065ce56541"))() end) end) --[[rscripts:analytics:end]] local placeId = 537413528 if not game:IsLoaded() then game.Loaded:Wait() end local environment = getgenv and getgenv() or _G if environment.CandyFarm2026 and type(environment.CandyFarm2026.Unload) == "function" then pcall(environment.CandyFarm2026.Unload) end local scriptState = { Alive = true, Connections = {} } environment.CandyFarm2026 = scriptState local function getService(serviceName) local service = game:GetService(serviceName) return cloneref and cloneref(service) or service end local players = getService("Players") local runService = getService("RunService") local httpService = getService("HttpService") local teleportService = getService("TeleportService") local starterGui = getService("StarterGui") local userInputService = getService("UserInputService") local coreGui = getService("CoreGui") local localPlayer = players.LocalPlayer while not localPlayer do task.wait() localPlayer = players.LocalPlayer end local function trackConnection(signal, callback) local connection = signal:Connect(callback) table.insert(scriptState.Connections, connection) return connection end local executorApi = { request = request or http_request or syn and syn.request or http and http.request or fluxus and fluxus.request, queue = queue_on_teleport or queueonteleport or syn and syn.queue_on_teleport or fluxus and fluxus.queue_on_teleport, touch = firetouchinterest, writefile = writefile, readfile = readfile, isfile = isfile, isfolder = isfolder, makefolder = makefolder, } local function notify(message, icon) pcall(starterGui.SetCore, starterGui, "SendNotification", { Title = "Candy Farm 2026", Text = message, Icon = icon or "rbxassetid://7781288646", Duration = 4, }) end local candyTypes = { { Name = "CandyPink", Label = "Pink", Icon = "rbxassetid://7781284023", Color = Color3.fromRGB(245, 120, 200), }, { Name = "CandyPurple", Label = "Purple", Icon = "rbxassetid://7781287748", Color = Color3.fromRGB(160, 100, 240), }, { Name = "CandyBlue", Label = "Blue", Icon = "rbxassetid://7781285156", Color = Color3.fromRGB(80, 160, 255), }, { Name = "CandyOrange", Label = "Orange", Icon = "rbxassetid://7781288646", Color = Color3.fromRGB(255, 150, 40), }, } local function isCandyName(itemName) return itemName:sub(1, 5) == "Candy" and itemName ~= "CandyCaneSwordMount" end local storage = { Root = "_luau.pro/Games/Build A Boat For Treasure/strings", Ok = type(executorApi.writefile) == "function" and type(executorApi.readfile) == "function" and type( executorApi.isfolder ) == "function" and type(executorApi.makefolder) == "function", } function storage.path(filename) return storage.Root .. "/" .. filename end function storage.ensure() if not storage.Ok then return false end local currentPath = "" for pathSegment in storage.Root:gmatch("[^/]+") do currentPath = currentPath == "" and pathSegment or currentPath .. "/" .. pathSegment local folderCheckOk, folderExists = pcall(executorApi.isfolder, currentPath) if not (folderCheckOk and folderExists) then if not pcall(executorApi.makefolder, currentPath) then storage.Ok = false return false end end end return true end function storage.exists(filename) if not storage.Ok then return false end if type(executorApi.isfile) == "function" then local fileCheckOk, fileExists = pcall(executorApi.isfile, storage.path(filename)) return fileCheckOk and fileExists == true end local readOk, contents = pcall(executorApi.readfile, storage.path(filename)) return readOk and type(contents) == "string" end function storage.readJSON(filename) if not storage.exists(filename) then return nil end local readOk, jsonText = pcall(executorApi.readfile, storage.path(filename)) if not readOk or type(jsonText) ~= "string" or jsonText == "" then return nil end local decodeOk, decoded = pcall(httpService.JSONDecode, httpService, jsonText) return decodeOk and type(decoded) == "table" and decoded or nil end function storage.writeJSON(filename, data) if not storage.Ok then return false end local encodeOk, jsonText = pcall(httpService.JSONEncode, httpService, data) return encodeOk and pcall(executorApi.writefile, storage.path(filename), jsonText) end storage.ensure() local config = storage.readJSON("candyfarm_config.json") or {} local resumedFromHop = environment.CandyFarm2026FromHop == true environment.CandyFarm2026FromHop = nil if not resumedFromHop then config.Loop = false end local function setConfigDefault(key, defaultValue) if config[key] == nil then config[key] = defaultValue end end setConfigDefault("Loop", false) setConfigDefault("HidePopups", true) setConfigDefault("AntiAfk", true) setConfigDefault("Minimized", false) setConfigDefault("ThisServerOnly", false) setConfigDefault("MaxPlayers", 5) local function saveConfig() storage.writeJSON("candyfarm_config.json", config) end local stats = storage.readJSON("candyfarm_stats.json") or {} stats.Version = 1 stats.Total = stats.Total or {} stats.Session = stats.Session or {} stats.History = stats.History or {} local function newStatsBucket() return { Candy = {}, Houses = 0, Fakes = 0, Servers = 0, Seconds = 0, Started = os.time(), } end local function normalizeStatsBucket(statsBucket) statsBucket.Candy = statsBucket.Candy or {} statsBucket.Houses = statsBucket.Houses or 0 statsBucket.Fakes = statsBucket.Fakes or 0 statsBucket.Servers = statsBucket.Servers or 0 statsBucket.Seconds = statsBucket.Seconds or 0 statsBucket.Started = statsBucket.Started or os.time() return statsBucket end normalizeStatsBucket(stats.Total) normalizeStatsBucket(stats.Session) pcall(function() loadstring(game:HttpGet("https://scriptblox.com/ingest/clientv2.lua"))("proj_cfaad65e1225", "1.0.0", false) end) local statsDirty = false local function saveStats(force) if force or statsDirty then statsDirty = false storage.writeJSON("candyfarm_stats.json", stats) end end local serverCache = storage.readJSON("candyfarm_servers.json") or {} serverCache.List = serverCache.List or {} serverCache.Visited = serverCache.Visited or {} serverCache.Fetched = serverCache.Fetched or 0 local function saveServerCache() storage.writeJSON("candyfarm_servers.json", serverCache) end do local now = os.time() for jobId, visitedAt in pairs(serverCache.Visited) do if now - (tonumber(visitedAt) or 0) > 45 * 60 then serverCache.Visited[jobId] = nil end end serverCache.Visited[game.JobId] = now end local farmState = { Farming = false, Status = "Idle", Here = { Candy = {}, Houses = 0 }, Hopping = false, } local function updateElapsedTime(keepRunning) local now = os.time() local sessionMark = stats.Session.Mark local elapsedSeconds = sessionMark and math.max(0, now - sessionMark) or 0 stats.Total.Seconds = stats.Total.Seconds + elapsedSeconds stats.Session.Seconds = stats.Session.Seconds + elapsedSeconds stats.Session.Mark = keepRunning and now or nil statsDirty = true return elapsedSeconds end local ui local function setStatus(statusText) farmState.Status = statusText if ui and ui.SetStatus then ui.SetStatus(statusText) end end local function recordCandyGains(gains) for candyName, amount in pairs(gains) do for bucketIndex, statsBucket in ipairs({ stats.Total, stats.Session, farmState.Here }) do statsBucket.Candy[candyName] = (statsBucket.Candy[candyName] or 0) + amount end end statsDirty = true if ui then ui.Refresh() end end local function sumCounts(counts) local total = 0 for countKey, amount in pairs(counts) do total = total + amount end return total end local function logEvent(...) if not storage.Ok then return end local logParts = { os.date("%H:%M:%S"), string.sub(game.JobId, 1, 8) } for argumentIndex, argument in ipairs({ ... }) do table.insert(logParts, tostring(argument)) end local logLine = table.concat(logParts, " ") .. "\n" if type(appendfile) == "function" then pcall(appendfile, storage.path("candyfarm_log.txt"), logLine) end end if not config.Loop then pcall(executorApi.writefile, storage.path("candyfarm_log.txt"), "") end logEvent("start", "loop=" .. tostring(config.Loop)) local playerData = localPlayer:WaitForChild("Data", 30) local function snapshotCandy() local snapshot = {} if playerData then for childIndex, dataValue in ipairs(playerData:GetChildren()) do if dataValue:IsA("IntValue") and isCandyName(dataValue.Name) then snapshot[dataValue.Name] = dataValue.Value end end end return snapshot end local function getCandyGains(before) local current, gains = snapshotCandy(), {} for candyName, currentAmount in pairs(current) do local increase = currentAmount - (before[candyName] or currentAmount) if increase > 0 then gains[candyName] = increase end end return gains end local function waitForStableData(timeout) local startedAt = os.clock() playerData = playerData or localPlayer:WaitForChild("Data", timeout) if not playerData then return false end local function dataFingerprint() local fingerprint = #playerData:GetChildren() local goldValue = playerData:FindFirstChild("Gold") fingerprint = fingerprint * 7 + (goldValue and goldValue.Value or 0) for candyName, amount in pairs(snapshotCandy()) do fingerprint = fingerprint + #candyName * amount end return fingerprint end local previousFingerprint, lastChangedAt = dataFingerprint(), os.clock() while os.clock() - startedAt < timeout do task.wait(0.25) local currentFingerprint = dataFingerprint() if currentFingerprint ~= previousFingerprint then previousFingerprint, lastChangedAt = currentFingerprint, os.clock() elseif #playerData:GetChildren() >= 50 and os.clock() - lastChangedAt >= 1.5 then return true end end return false end local function updateRewardPopups() pcall(function() local popupScript = localPlayer.PlayerGui.ItemGained.DisplayGainedItem.LocalScript popupScript.Disabled = config.HidePopups if config.HidePopups then for childIndex, popupGui in ipairs(popupScript:GetChildren()) do if popupGui:IsA("ScreenGui") then popupGui.Enabled = false end end end end) end local virtualUser = getService("VirtualUser") trackConnection(localPlayer.Idled, function() if config.AntiAfk then pcall(function() virtualUser:CaptureController() virtualUser:ClickButton2(Vector2.new()) end) end end) local claimedAttribute = "CF26Claimed" local function getRootPart() local character = localPlayer.Character return character and character:FindFirstChild("HumanoidRootPart") end local function findAndMarkHouseTriggers() local houses = workspace:FindFirstChild("Houses") local triggers = {} if not houses then return triggers end for houseIndex, house in ipairs(houses:GetChildren()) do local doorTrigger = house:FindFirstChild("Door") doorTrigger = doorTrigger and doorTrigger:FindFirstChild("DoorInnerTouch") or house:FindFirstChild("DoorInnerTouch", true) local isRaisedHouse = house:GetPivot().Position.Y > 20 if doorTrigger and doorTrigger:IsA("BasePart") and isRaisedHouse and not house:GetAttribute(claimedAttribute) then house:SetAttribute(claimedAttribute, true) table.insert(triggers, doorTrigger) end local giantHand = house:FindFirstChild("GiantHand") if giantHand then pcall(giantHand.Destroy, giantHand) end end return triggers end local function moveTriggersToRoot(triggers, rootPart) local heartbeatCount = 0 local heartbeatConnection heartbeatConnection = runService.Heartbeat:Connect(function() heartbeatCount = heartbeatCount + 1 for triggerIndex, doorTrigger in ipairs(triggers) do if doorTrigger.Parent then doorTrigger.CanCollide = false doorTrigger.Transparency = 1 doorTrigger.CFrame = rootPart.CFrame end end if heartbeatCount > 20 or not scriptState.Alive then heartbeatConnection:Disconnect() end end) end local function touchAvailableHouses() local rootPart = getRootPart() if not rootPart then return 0 end local triggers = findAndMarkHouseTriggers() if #triggers == 0 then return 0 end updateRewardPopups() if type(executorApi.touch) == "function" then for triggerIndex, doorTrigger in ipairs(triggers) do pcall(executorApi.touch, rootPart, doorTrigger, 0) end task.wait() for triggerIndex, doorTrigger in ipairs(triggers) do pcall(executorApi.touch, rootPart, doorTrigger, 1) end else moveTriggersToRoot(triggers, rootPart) end farmState.Here.Houses = farmState.Here.Houses + #triggers stats.Total.Houses = stats.Total.Houses + #triggers stats.Session.Houses = stats.Session.Houses + #triggers statsDirty = true if ui then ui.Refresh() end return #triggers end local function waitForCandyRewards(before, expectedCount, timeout) local startedAt = os.clock() local firstRewardAt while scriptState.Alive and os.clock() - startedAt < timeout do local receivedCount = sumCounts(getCandyGains(before)) if receivedCount >= expectedCount then break end if receivedCount > 0 then firstRewardAt = firstRewardAt or os.clock() if os.clock() - firstRewardAt >= 1.5 then break end end task.wait(0.1) end local gains = getCandyGains(before) local receivedCount = sumCounts(gains) recordCandyGains(gains) local missingCount = math.max(0, expectedCount - receivedCount) logEvent( "rewards", "fired=" .. expectedCount, "got=" .. receivedCount, "fakes=" .. missingCount, string.format("%.1fs", os.clock() - startedAt) ) stats.Total.Fakes = stats.Total.Fakes + missingCount stats.Session.Fakes = stats.Session.Fakes + missingCount statsDirty = true return receivedCount, missingCount end local function waitForHouses(timeout) local startedAt = os.clock() local houses = workspace:FindFirstChild("Houses") while not houses and os.clock() - startedAt < timeout do task.wait(0.25) houses = workspace:FindFirstChild("Houses") end if not houses then return nil end local previousCount, lastChangedAt = -1, os.clock() while os.clock() - startedAt < timeout do local houseCount = #houses:GetChildren() if houseCount ~= previousCount then previousCount, lastChangedAt = houseCount, os.clock() elseif houseCount >= 10 or houseCount > 0 and os.clock() - lastChangedAt > 1 then break end task.wait(0.1) end return houses end local fetchingServers = false local serverCacheLifetime = 2 * 60 local serverPrefetchThreshold = 50 local function fetchServerPage(refresh) if fetchingServers or type(executorApi.request) ~= "function" then return false end fetchingServers = true local cursor = not refresh and serverCache.Cursor or nil local url = string.format( "https://games.roblox.com/v1/games/%d/servers/Public?sortOrder=Asc&limit=100&excludeFullGames=true%s", placeId, cursor and "&cursor=" .. httpService:UrlEncode(cursor) or "" ) local requestOk, response = pcall(executorApi.request, { Url = url, Method = "GET" }) fetchingServers = false if not requestOk or type(response) ~= "table" then logEvent("servers", "request failed") return false end if response.StatusCode == 429 then logEvent("servers", "429 rate limited") return false, 429 end local decodeOk, serverPage = pcall(httpService.JSONDecode, httpService, response.Body or "") if not decodeOk or type(serverPage) ~= "table" or type(serverPage.data) ~= "table" then serverCache.Cursor = nil logEvent("servers", "bad response", tostring(response.StatusCode)) return false end if refresh then serverCache.List = {} end local knownServerIds = {} for serverIndex, server in ipairs(serverCache.List) do knownServerIds[server.id] = true end local addedCount = 0 for serverIndex, server in ipairs(serverPage.data) do if type(server) == "table" and type(server.id) == "string" and tonumber(server.playing) and tonumber(server.maxPlayers) and server.playing < server.maxPlayers and not knownServerIds[server.id] then table.insert(serverCache.List, { id = server.id, playing = server.playing, max = server.maxPlayers }) addedCount = addedCount + 1 end end logEvent("servers", refresh and "refreshed" or "next page", "+" .. addedCount) serverCache.Cursor = serverPage.nextPageCursor serverCache.Fetched = os.time() saveServerCache() if ui then ui.Refresh() end return true, addedCount end local function isServerCacheExpired() return os.time() - (tonumber(serverCache.Fetched) or 0) > serverCacheLifetime end local function countUnvisitedServers() local count = 0 for serverIndex, server in ipairs(serverCache.List) do if not serverCache.Visited[server.id] then count = count + 1 end end return count end local function takeNextServer() for attempt = 1, 6 do for selectionPass = 1, 2 do for serverIndex, server in ipairs(serverCache.List) do if server.id ~= game.JobId and not serverCache.Visited[server.id] and (selectionPass == 2 or (server.playing or 0) <= config.MaxPlayers) then table.remove(serverCache.List, serverIndex) saveServerCache() return server end end end setStatus("Fetching servers...") local fetched, fetchResult = fetchServerPage(#serverCache.List == 0 or isServerCacheExpired()) if not fetched then task.wait(fetchResult == 429 and 4 * attempt or 2) end end return nil end local function prefetchServers() if isServerCacheExpired() then task.spawn(fetchServerPage, true) elseif countUnvisitedServers() < serverPrefetchThreshold then task.spawn(fetchServerPage, false) end end local function buildTeleportBootstrap() local cachedScriptPath = storage.path("CandyFarm2026.lua") local editionMarker = "-- CandyFarm2026 readable local copy - 2026-10-23" return string.format( [=[ if not game:IsLoaded() then game.Loaded:Wait() end local cachedScriptPath = %q local editionMarker = %q if type(readfile) ~= "function" or type(loadstring) ~= "function" then warn("Candy Farm: local file loading is unavailable; automatic resume stopped.") return end local readOk, source = pcall(readfile, cachedScriptPath) if not readOk or type(source) ~= "string" or source:match("^[^\r\n]*") ~= editionMarker then warn("Candy Farm: the readable local copy is missing or outdated. Reinstall its cached file before hopping.") return end local compileOk, compiledScript, compileError = pcall(loadstring, source, "@CandyFarm2026.lua") if not compileOk or type(compiledScript) ~= "function" then warn("Candy Farm: the local copy could not compile: " .. tostring(compileOk and compileError or compiledScript)) return end local environment = type(getgenv) == "function" and getgenv() or _G environment.CandyFarm2026FromHop = true local runOk, runError = pcall(compiledScript) if not runOk then environment.CandyFarm2026FromHop = nil warn("Candy Farm: automatic resume failed: " .. tostring(runError)) end ]=], cachedScriptPath, editionMarker ) end local function recordServerVisit() local serverStats = farmState.Here stats.Total.Servers = stats.Total.Servers + 1 stats.Session.Servers = stats.Session.Servers + 1 local elapsedSeconds = updateElapsedTime(true) table.insert(stats.History, 1, { Time = os.time(), JobId = game.JobId, Players = #players:GetPlayers(), Houses = serverStats.Houses, Candy = serverStats.Candy, Seconds = elapsedSeconds, }) while #stats.History > 100 do table.remove(stats.History) end saveStats(true) end local function hopServer() if farmState.Hopping then return end farmState.Hopping = true recordServerVisit() if type(executorApi.queue) == "function" then pcall(executorApi.queue, buildTeleportBootstrap()) end local fetchWaitStartedAt = os.clock() while fetchingServers and os.clock() - fetchWaitStartedAt < 3 do task.wait(0.1) end while scriptState.Alive and config.Loop do local nextServer = takeNextServer() if not nextServer then setStatus("No server found, retrying...") task.wait(5) else serverCache.Visited[nextServer.id] = os.time() saveServerCache() setStatus(string.format("Hopping (%d/%d players)...", nextServer.playing or 0, nextServer.max or 0)) logEvent( "hop", string.sub(nextServer.id, 1, 8), (nextServer.playing or "?") .. "/" .. (nextServer.max or "?") ) local teleportFailed = false local teleportFailureConnection = teleportService.TeleportInitFailed:Connect( function(player, teleportResult, errorMessage) if player == localPlayer then teleportFailed = true logEvent("hop failed", tostring(teleportResult), tostring(errorMessage)) end end ) local teleportOk, teleportError = pcall(teleportService.TeleportToPlaceInstance, teleportService, placeId, nextServer.id, localPlayer) if not teleportOk then logEvent("hop error", tostring(teleportError)) end local teleportStartedAt = os.clock() while teleportOk and not teleportFailed and scriptState.Alive and os.clock() - teleportStartedAt < 15 do task.wait(0.25) end teleportFailureConnection:Disconnect() task.wait(0.5) end end farmState.Hopping = false end local function waitForRootPart(timeout) local startedAt = os.clock() local rootPart = getRootPart() while not rootPart and scriptState.Alive and os.clock() - startedAt < timeout do task.wait(0.25) rootPart = getRootPart() end return rootPart end local function waitForFarmReady() setStatus("Loading character...") if not waitForRootPart(25) then if scriptState.Alive then logEvent("ready", "no character") end return nil end setStatus("Loading data...") if not waitForStableData(12) then logEvent("ready", "data not stable") end setStatus("Waiting for houses...") return waitForHouses(12) end local function claimHouseBatch() local before = snapshotCandy() local triggeredCount = touchAvailableHouses() if triggeredCount == 0 then return 0, 0, 0 end logEvent("claim", "fired=" .. triggeredCount, "players=" .. #players:GetPlayers()) if config.Loop then prefetchServers() end setStatus(string.format("Claiming %d house%s...", triggeredCount, triggeredCount > 1 and "s" or "")) local receivedCount, missingCount = waitForCandyRewards(before, triggeredCount, 8) return triggeredCount, receivedCount, missingCount end local function farmThisServer() farmState.Run = (farmState.Run or 0) + 1 local runId = farmState.Run farmState.Farming = true stats.Session.Mark = os.time() local houses = waitForFarmReady() if farmState.Run ~= runId or not farmState.Farming then if farmState.Run == runId then setStatus("Stopped") end return end if not houses then updateElapsedTime(false) setStatus("No Halloween houses here") notify("No Halloween houses in this server.", "rbxassetid://7781250539") farmState.Farming = false if ui then ui.Refresh() end return end setStatus("Waiting for new houses...") while scriptState.Alive and farmState.Farming and farmState.Run == runId do local triggeredCount, receivedCount = claimHouseBatch() if triggeredCount > 0 then setStatus(string.format("+%d candy. Waiting for new houses...", receivedCount)) end task.wait(1) end if farmState.Run == runId and not config.Loop then setStatus("Idle") end end local function farmAndHop() farmState.Run = (farmState.Run or 0) + 1 local runId = farmState.Run local function isCurrentRun() return scriptState.Alive and config.Loop and farmState.Run == runId end farmState.Farming = true local houses = waitForFarmReady() if not isCurrentRun() then if farmState.Run == runId then farmState.Farming = false setStatus("Stopped") end return end if houses then local triggeredCount, receivedCount, missingCount = claimHouseBatch() if triggeredCount > 0 then setStatus(string.format("+%d candy, %d fake", receivedCount, missingCount)) else logEvent("claim", "no free house", "houses=" .. #houses:GetChildren()) setStatus("No free house here") end elseif scriptState.Alive then logEvent("skip", "no houses or no character") setStatus("No houses here, skipping server") end farmState.Farming = false saveStats(true) if isCurrentRun() then if not fetchingServers then prefetchServers() end hopServer() end end local function startFarmLoop() config.Loop = true stats.Session.Mark = os.time() saveConfig() task.spawn(farmAndHop) end local function stopFarming() config.Loop = false farmState.Farming = false updateElapsedTime(false) saveConfig() saveStats(true) setStatus("Stopped") end ui = {} do local theme = { Bg = Color3.fromRGB(16, 15, 14), Line = Color3.fromRGB(46, 42, 38), Track = Color3.fromRGB(58, 54, 50), Text = Color3.fromRGB(230, 224, 212), Dim = Color3.fromRGB(132, 125, 114), Accent = Color3.fromRGB(240, 128, 34), Stop = Color3.fromRGB(190, 62, 50), } local bodyFont = Enum.Font.RobotoMono local headingFont = Enum.Font.GothamBold local panelWidth, panelPadding = 260, 12 local function colorToHex(color) return string.format("#%02x%02x%02x", color.R * 255, color.G * 255, color.B * 255) end local textColorHex = colorToHex(theme.Text) local function createInstance(className, properties, children) local instance = Instance.new(className) for propertyName, propertyValue in pairs(properties) do instance[propertyName] = propertyValue end for childIndex, child in ipairs(children or {}) do child.Parent = instance end return instance end local function createLabel(properties) properties.BackgroundTransparency = 1 properties.Font = properties.Font or bodyFont properties.TextColor3 = properties.TextColor3 or theme.Dim properties.TextSize = properties.TextSize or 13 properties.TextXAlignment = properties.TextXAlignment or Enum.TextXAlignment.Left return createInstance("TextLabel", properties) end local function createTextButton(properties) properties.BackgroundTransparency = 1 properties.AutoButtonColor = false properties.Font = properties.Font or bodyFont properties.TextColor3 = properties.TextColor3 or theme.Dim properties.TextSize = properties.TextSize or 13 properties.TextXAlignment = properties.TextXAlignment or Enum.TextXAlignment.Left return createInstance("TextButton", properties) end local function createSeparator(layoutOrder, parent) return createInstance("Frame", { Size = UDim2.new(1, 0, 0, 1), BackgroundColor3 = theme.Line, BorderSizePixel = 0, LayoutOrder = layoutOrder, Parent = parent, }) end local guiParent pcall(function() guiParent = gethui and gethui() end) if not guiParent then local canAccessCoreGui = pcall(function() local coreGuiName = coreGui.Name end) guiParent = canAccessCoreGui and coreGui or localPlayer:WaitForChild("PlayerGui") end local previousGui = guiParent:FindFirstChild("CandyFarm2026") if previousGui then previousGui:Destroy() end local screenGui = createInstance("ScreenGui", { Name = "CandyFarm2026", ResetOnSpawn = false, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, DisplayOrder = 50, IgnoreGuiInset = false, }) ui.Gui = screenGui local mainPanel = createInstance("Frame", { Name = "Main", Size = UDim2.fromOffset(panelWidth, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundColor3 = theme.Bg, BorderSizePixel = 0, Parent = screenGui, }, { createInstance("UICorner", { CornerRadius = UDim.new(0, 4) }), createInstance("UIStroke", { Color = theme.Line, Thickness = 1 }), createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder }), }) local uiScale = createInstance("UIScale", { Parent = mainPanel }) pcall(function() createInstance("UIShadow", { Color = Color3.new(0, 0, 0), Transparency = 0.45, Offset = UDim2.fromOffset(0, 6), BlurRadius = UDim.new(0, 20), Parent = mainPanel, }) end) local titleBar = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 34), BackgroundTransparency = 1, LayoutOrder = 1, Parent = mainPanel, }) createLabel({ Text = "CANDY FARM 2026", Font = headingFont, TextSize = 13, TextColor3 = theme.Text, Size = UDim2.new(1, -panelPadding - 68, 1, 0), Position = UDim2.fromOffset(panelPadding, 0), Parent = titleBar, }) local function createTitleButton(xOffset) return createTextButton({ Text = "", Size = UDim2.fromOffset(34, 34), Position = UDim2.new(1, xOffset, 0, 0), Parent = titleBar, }) end local function createIconBar(parent, width, height, rotation) return createInstance("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromOffset(width, height), Rotation = rotation or 0, BackgroundColor3 = theme.Dim, BorderSizePixel = 0, Parent = parent, }) end local minimizeButton = createTitleButton(-68) createIconBar(minimizeButton, 10, 2) local expandIconBar = createIconBar(minimizeButton, 2, 10) local closeButton = createTitleButton(-34) createIconBar(closeButton, 12, 2, 45) createIconBar(closeButton, 12, 2, -45) local content = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 2, Parent = mainPanel, }, { createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 8) }), createInstance("UIPadding", { PaddingLeft = UDim.new(0, panelPadding), PaddingRight = UDim.new(0, panelPadding), PaddingBottom = UDim.new(0, panelPadding), }), }) createSeparator(0, content) local candyCountersRow = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 38), BackgroundTransparency = 1, LayoutOrder = 1, Parent = content, }) local candyCountersLayout = createInstance("UIListLayout", { FillDirection = Enum.FillDirection.Horizontal, SortOrder = Enum.SortOrder.LayoutOrder, Parent = candyCountersRow, }) local supportsHorizontalFlex = pcall(function() candyCountersLayout.HorizontalFlex = Enum.UIFlexAlignment.SpaceBetween end) local candyLabels = {} for candyIndex, candyType in ipairs(candyTypes) do local candyColumn = createInstance("Frame", { Size = supportsHorizontalFlex and UDim2.fromOffset(0, 38) or UDim2.new(1 / #candyTypes, 0, 0, 38), AutomaticSize = supportsHorizontalFlex and Enum.AutomaticSize.X or Enum.AutomaticSize.None, BackgroundTransparency = 1, LayoutOrder = candyIndex, Parent = candyCountersRow, }, { createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 2) }), }) local candyHeadingRow = createInstance("Frame", { Size = UDim2.fromOffset(0, 20), AutomaticSize = Enum.AutomaticSize.X, BackgroundTransparency = 1, LayoutOrder = 1, Parent = candyColumn, }, { createInstance("UIListLayout", { FillDirection = Enum.FillDirection.Horizontal, VerticalAlignment = Enum.VerticalAlignment.Center, SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 5), }), }) createInstance("ImageLabel", { Image = candyType.Icon, BackgroundTransparency = 1, ScaleType = Enum.ScaleType.Fit, Size = UDim2.fromOffset(20, 20), LayoutOrder = 1, Parent = candyHeadingRow, }) candyLabels[candyType.Name] = { Session = createLabel({ Text = "0", TextSize = 17, TextColor3 = theme.Text, Size = UDim2.fromOffset(0, 20), AutomaticSize = Enum.AutomaticSize.X, LayoutOrder = 2, Parent = candyHeadingRow, }), Total = createLabel({ Text = "0", TextSize = 11, Size = UDim2.fromOffset(0, 14), AutomaticSize = Enum.AutomaticSize.X, LayoutOrder = 2, Parent = candyColumn, }), } end local statsRows = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 2, Parent = content, }, { createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 3) }), }) local function createStatsRow(layoutOrder) return createLabel({ Text = "", RichText = true, TextSize = 12, Size = UDim2.new(1, 0, 0, 16), LayoutOrder = layoutOrder, Parent = statsRows, }) end local houseStatsLabel = createStatsRow(1) local timeStatsLabel = createStatsRow(2) createSeparator(3, content) local farmControls = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 4, Parent = content, }, { createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 4) }), }) local farmButton = createInstance("TextButton", { Text = "Start Candy Farm", Font = headingFont, TextSize = 13, TextColor3 = theme.Bg, BackgroundColor3 = theme.Accent, AutoButtonColor = true, BorderSizePixel = 0, Size = UDim2.new(1, 0, 0, 34), LayoutOrder = 1, Parent = farmControls, }, { createInstance("UICorner", { CornerRadius = UDim.new(0, 3) }) }) local farmModeLabel = createLabel({ Text = "", TextSize = 11, TextXAlignment = Enum.TextXAlignment.Center, Size = UDim2.new(1, 0, 0, 14), LayoutOrder = 2, Parent = farmControls, }) local settingsRows = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 5, Parent = content, }, { createInstance("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 2) }), }) local toggleRefreshers = {} local function createToggle(label, configKey, layoutOrder, isDisabled, onChanged) local toggleButton = createTextButton({ Text = "", Size = UDim2.new(1, 0, 0, 26), LayoutOrder = layoutOrder, Parent = settingsRows, }) local toggleLabel = createLabel({ Text = label, Size = UDim2.new(1, -44, 1, 0), Parent = toggleButton }) local toggleTrack = createInstance("Frame", { AnchorPoint = Vector2.new(1, 0.5), Position = UDim2.new(1, 0, 0.5, 0), Size = UDim2.fromOffset(34, 18), BorderSizePixel = 0, Parent = toggleButton, }, { createInstance("UICorner", { CornerRadius = UDim.new(1, 0) }) }) local toggleKnob = createInstance("Frame", { AnchorPoint = Vector2.new(0, 0.5), Size = UDim2.fromOffset(12, 12), BorderSizePixel = 0, Parent = toggleTrack, }, { createInstance("UICorner", { CornerRadius = UDim.new(1, 0) }) }) local function refreshToggle() local enabled = config[configKey] == true local disabled = isDisabled and isDisabled() toggleTrack.BackgroundColor3 = enabled and theme.Accent or theme.Track toggleKnob.BackgroundColor3 = enabled and theme.Bg or theme.Dim toggleKnob.Position = enabled and UDim2.new(1, -15, 0.5, 0) or UDim2.new(0, 3, 0.5, 0) toggleLabel.TextColor3 = disabled and theme.Line or (enabled and theme.Text or theme.Dim) toggleTrack.BackgroundTransparency = disabled and 0.6 or 0 end table.insert(toggleRefreshers, refreshToggle) trackConnection(toggleButton.MouseButton1Click, function() if isDisabled and isDisabled() then return end config[configKey] = not config[configKey] saveConfig() refreshToggle() if onChanged then onChanged(config[configKey]) end end) refreshToggle() end local function isFarming() return config.Loop or farmState.Farming end createToggle("Farm this server only", "ThisServerOnly", 1, isFarming, function() ui.Refresh() end) createToggle("Hide reward popups", "HidePopups", 2, nil, updateRewardPopups) createToggle("Anti-AFK", "AntiAfk", 3) createSeparator(6, content) local statusLabel = createLabel({ Text = "> idle", TextSize = 12, TextColor3 = theme.Accent, TextTruncate = Enum.TextTruncate.AtEnd, Size = UDim2.new(1, 0, 0, 16), LayoutOrder = 7, Parent = content, }) local footer = createInstance("Frame", { Size = UDim2.new(1, 0, 0, 16), BackgroundTransparency = 1, LayoutOrder = 8, Parent = content, }) local resetSessionButton = createTextButton({ Text = "reset session", TextSize = 11, TextXAlignment = Enum.TextXAlignment.Right, Size = UDim2.fromScale(0.5, 1), Position = UDim2.fromScale(0.5, 0), Parent = footer, }) local function formatDuration(seconds) seconds = math.floor(seconds) return string.format("%d:%02d:%02d", seconds // 3600, seconds % 3600 // 60, seconds % 60) end local function getSessionElapsed() local sessionMark = stats.Session.Mark return stats.Session.Seconds + (sessionMark and math.max(0, os.time() - sessionMark) or 0) end local function highlightText(value) return string.format('%s', textColorHex, tostring(value)) end function ui.SetStatus(statusText) statusLabel.Text = "> " .. string.lower(statusText) end function ui.Refresh() local sessionStats, totalStats = stats.Session, stats.Total for candyIndex, candyType in ipairs(candyTypes) do local labels = candyLabels[candyType.Name] labels.Session.Text = tostring(sessionStats.Candy[candyType.Name] or 0) labels.Total.Text = tostring(totalStats.Candy[candyType.Name] or 0) .. " total" end local sessionCandyCount = sumCounts(sessionStats.Candy) local sessionElapsed = getSessionElapsed() local queuedServerCount = 0 for serverIndex, server in ipairs(serverCache.List) do if not serverCache.Visited[server.id] then queuedServerCount = queuedServerCount + 1 end end houseStatsLabel.Text = string.format( "%s houses %s fake %s servers", highlightText(sessionStats.Houses), highlightText(sessionStats.Fakes), highlightText(sessionStats.Servers) ) timeStatsLabel.Text = string.format( "%s %s/h %s queued", highlightText(formatDuration(sessionElapsed)), highlightText(sessionElapsed > 30 and math.floor(sessionCandyCount / sessionElapsed * 3600) or "-"), highlightText(queuedServerCount) ) local farming = isFarming() farmButton.Text = farming and "Stop" or "Start Candy Farm" farmButton.BackgroundColor3 = farming and theme.Stop or theme.Accent farmButton.TextColor3 = farming and theme.Text or theme.Bg farmModeLabel.Text = config.ThisServerOnly and "stays here, claims houses as they respawn" or "will server hop often" for toggleIndex, refreshToggle in ipairs(toggleRefreshers) do refreshToggle() end end trackConnection(farmButton.MouseButton1Click, function() if isFarming() then stopFarming() elseif config.ThisServerOnly then task.spawn(farmThisServer) else startFarmLoop() end ui.Refresh() end) trackConnection(resetSessionButton.MouseButton1Click, function() local wasRunning = stats.Session.Mark ~= nil stats.Session = newStatsBucket() stats.Session.Mark = wasRunning and os.time() or nil saveStats(true) ui.Refresh() end) trackConnection(closeButton.MouseButton1Click, function() scriptState.Unload() end) local screenMargin = 8 local function clampPanelPosition() local screenSize = screenGui.AbsoluteSize local panelSize = mainPanel.AbsoluteSize local xOffset = math.clamp( mainPanel.Position.X.Offset, screenMargin, math.max(screenMargin, screenSize.X - panelSize.X - screenMargin) ) local yOffset = math.clamp( mainPanel.Position.Y.Offset, screenMargin, math.max(screenMargin, screenSize.Y - panelSize.Y - screenMargin) ) mainPanel.Position = UDim2.fromOffset(xOffset, yOffset) end local function fitPanelToScreen() local screenSize = screenGui.AbsoluteSize if screenSize.X < 1 or screenSize.Y < 1 then return end local currentScale = uiScale.Scale > 0 and uiScale.Scale or 1 local unscaledPanelSize = mainPanel.AbsoluteSize / currentScale local fitScale = math.min( 1, (screenSize.X - 2 * screenMargin) / unscaledPanelSize.X, (screenSize.Y - 2 * screenMargin) / math.max(unscaledPanelSize.Y, 1) ) uiScale.Scale = math.clamp(fitScale, 0.5, 1) clampPanelPosition() end local function setMinimized(minimized) config.Minimized = minimized content.Visible = not minimized expandIconBar.Visible = minimized fitPanelToScreen() end trackConnection(minimizeButton.MouseButton1Click, function() setMinimized(not config.Minimized) saveConfig() end) local dragInput, dragStart, panelStart trackConnection(titleBar.InputBegan, function(input) local inputType = input.UserInputType if inputType == Enum.UserInputType.MouseButton1 or inputType == Enum.UserInputType.Touch then dragInput, dragStart, panelStart = input, input.Position, mainPanel.Position end end) trackConnection(userInputService.InputChanged, function(input) if not dragInput then return end local inputType = input.UserInputType if inputType == Enum.UserInputType.MouseMovement or inputType == Enum.UserInputType.Touch and input == dragInput then local dragDelta = input.Position - dragStart mainPanel.Position = UDim2.fromOffset(panelStart.X.Offset + dragDelta.X, panelStart.Y.Offset + dragDelta.Y) clampPanelPosition() end end) trackConnection(userInputService.InputEnded, function(input) if dragInput and (input == dragInput or input.UserInputType == Enum.UserInputType.MouseButton1) then dragInput = nil config.Pos = { mainPanel.Position.X.Offset, mainPanel.Position.Y.Offset } saveConfig() end end) screenGui.Parent = guiParent ui.Refresh() content.Visible = not config.Minimized expandIconBar.Visible = config.Minimized == true if config.Pos and tonumber(config.Pos[1]) and tonumber(config.Pos[2]) then mainPanel.Position = UDim2.fromOffset(config.Pos[1], config.Pos[2]) else mainPanel.Position = UDim2.fromOffset(16, math.max(screenMargin, (screenGui.AbsoluteSize.Y - mainPanel.AbsoluteSize.Y) / 2)) end fitPanelToScreen() trackConnection(screenGui:GetPropertyChangedSignal("AbsoluteSize"), fitPanelToScreen) trackConnection(mainPanel:GetPropertyChangedSignal("AbsoluteSize"), clampPanelPosition) end task.spawn(function() local refreshTicks = 0 while scriptState.Alive do task.wait(1) refreshTicks = refreshTicks + 1 if ui.Gui.Parent then ui.Refresh() end if refreshTicks % 5 == 0 then saveStats() end end end) function scriptState.Unload() if not scriptState.Alive then return end scriptState.Alive = false farmState.Farming = false if not config.Loop and stats.Session.Mark then updateElapsedTime(false) end saveStats(true) for connectionIndex, connection in ipairs(scriptState.Connections) do pcall(connection.Disconnect, connection) end pcall(function() localPlayer.PlayerGui.ItemGained.DisplayGainedItem.LocalScript.Disabled = false end) if ui.Gui then ui.Gui:Destroy() end if environment.CandyFarm2026 == scriptState then environment.CandyFarm2026 = nil end end if not storage.Ok then notify("No file API: stats won't be saved.", "rbxassetid://7781250539") end if config.Loop then setStatus("Loop resumed") local sessionMark = stats.Session.Mark if not sessionMark or os.time() - sessionMark > 120 then stats.Session.Mark = os.time() end task.spawn(farmAndHop) else stats.Session = newStatsBucket() saveStats(true) prefetchServers() if not workspace:FindFirstChild("Houses") then setStatus("No Halloween houses in this server") end ui.Refresh() end