-- Remote Looper (Modern Dynamic Sidebar Panel, Non-Sticky Drag) -- Dynamic Remotes with Stats + Config (SeedCollect & GrassCollect) -- Place as a LocalScript in StarterPlayerScripts (or StarterGui) --===================== -- Services & Remotes --===================== local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local UserInputService = game:GetService("UserInputService") local TweenService = game:GetService("TweenService") local RemotesFolder = ReplicatedStorage:WaitForChild("Remotes") local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui") --===================== -- Known Remotes List --===================== local knownRemotes = { "IncreaseTree", "IncreaseSilver", "IncreaseMuscle", "GrassCollect", -- configurable "IncreasePop", "SeedCollect", -- configurable } --===================== -- GUI --===================== local sg = Instance.new("ScreenGui") sg.Name = "RemoteLooperGUI" sg.ResetOnSpawn = false sg.IgnoreGuiInset = true sg.ZIndexBehavior = Enum.ZIndexBehavior.Sibling sg.Parent = playerGui local baseWidth = 400 local panelWidth = 200 local panelGap = 20 local contentBasePosX = 160 local mainFrame = Instance.new("Frame") mainFrame.Name = "MainFrame" mainFrame.Size = UDim2.fromOffset(baseWidth, 240) mainFrame.Position = UDim2.new(0, 20, 0, 80) mainFrame.BackgroundColor3 = Color3.fromRGB(255, 255, 255) mainFrame.BackgroundTransparency = 0.4 mainFrame.BorderSizePixel = 0 mainFrame.Parent = sg Instance.new("UICorner", mainFrame).CornerRadius = UDim.new(0, 12) local stroke = Instance.new("UIStroke") stroke.Color = Color3.fromRGB(200, 200, 200) stroke.Transparency = 0.5 stroke.Parent = mainFrame -- Close Button local closeBtn = Instance.new("TextButton") closeBtn.Size = UDim2.fromOffset(30, 30) closeBtn.Position = UDim2.new(1, -35, 0, 5) closeBtn.BackgroundColor3 = Color3.fromRGB(255, 100, 100) closeBtn.Text = "×" closeBtn.TextColor3 = Color3.fromRGB(255, 255, 255) closeBtn.Font = Enum.Font.GothamBold closeBtn.TextSize = 20 closeBtn.AutoButtonColor = false closeBtn.Parent = mainFrame Instance.new("UICorner", closeBtn).CornerRadius = UDim.new(0, 15) closeBtn.MouseEnter:Connect(function() TweenService:Create(closeBtn, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(220, 80, 80)}):Play() end) closeBtn.MouseLeave:Connect(function() TweenService:Create(closeBtn, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(255, 100, 100)}):Play() end) -- Sidebar (Selected list) local sidebar = Instance.new("Frame") sidebar.Name = "Sidebar" sidebar.Size = UDim2.new(0, 140, 1, -60) sidebar.Position = UDim2.fromOffset(10, 10) sidebar.BackgroundColor3 = Color3.fromRGB(255, 255, 255) sidebar.BackgroundTransparency = 0.6 sidebar.BorderSizePixel = 0 sidebar.Parent = mainFrame Instance.new("UICorner", sidebar).CornerRadius = UDim.new(0, 8) local sidebarTitle = Instance.new("TextLabel") sidebarTitle.Size = UDim2.new(1, -12, 0, 28) sidebarTitle.Position = UDim2.fromOffset(6, 8) sidebarTitle.BackgroundTransparency = 1 sidebarTitle.Text = "Selected" sidebarTitle.TextColor3 = Color3.fromRGB(100, 100, 100) sidebarTitle.Font = Enum.Font.GothamSemibold sidebarTitle.TextSize = 14 sidebarTitle.TextXAlignment = Enum.TextXAlignment.Left sidebarTitle.Parent = sidebar -- Stats Panel local statsPanel = Instance.new("Frame") statsPanel.Name = "StatsPanel" statsPanel.Size = UDim2.new(0, panelWidth, 1, -60) statsPanel.Position = UDim2.fromOffset(contentBasePosX, 10) statsPanel.BackgroundColor3 = Color3.fromRGB(255, 255, 255) statsPanel.BackgroundTransparency = 0.6 statsPanel.BorderSizePixel = 0 statsPanel.Visible = false statsPanel.Parent = mainFrame Instance.new("UICorner", statsPanel).CornerRadius = UDim.new(0, 8) local statsTitle = Instance.new("TextLabel") statsTitle.Size = UDim2.new(1, -12, 0, 28) statsTitle.Position = UDim2.fromOffset(6, 8) statsTitle.BackgroundTransparency = 1 statsTitle.Text = "Available Stats" statsTitle.TextColor3 = Color3.fromRGB(100, 100, 100) statsTitle.Font = Enum.Font.GothamSemibold statsTitle.TextSize = 14 statsTitle.TextXAlignment = Enum.TextXAlignment.Left statsTitle.Parent = statsPanel local searchBox = Instance.new("TextBox") searchBox.Size = UDim2.new(1, -12, 0, 32) searchBox.Position = UDim2.fromOffset(6, 36) searchBox.BackgroundColor3 = Color3.fromRGB(245, 245, 245) searchBox.Text = "" searchBox.PlaceholderText = "Search remotes..." searchBox.TextColor3 = Color3.fromRGB(100, 100, 100) searchBox.Font = Enum.Font.Gotham searchBox.TextSize = 14 searchBox.ClearTextOnFocus = false searchBox.Parent = statsPanel Instance.new("UICorner", searchBox).CornerRadius = UDim.new(0, 6) Instance.new("UIPadding", searchBox).PaddingLeft = UDim.new(0, 12) local statsList = Instance.new("ScrollingFrame") statsList.Size = UDim2.new(1, -12, 1, -80) statsList.Position = UDim2.fromOffset(6, 74) statsList.BackgroundTransparency = 1 statsList.BorderSizePixel = 0 statsList.ScrollBarThickness = 6 statsList.ScrollBarImageColor3 = Color3.fromRGB(200, 200, 200) statsList.Parent = statsPanel local statsListLayout = Instance.new("UIListLayout") statsListLayout.SortOrder = Enum.SortOrder.Name statsListLayout.Padding = UDim.new(0, 4) statsListLayout.Parent = statsList -- Config Panel local configPanel = Instance.new("Frame") configPanel.Name = "ConfigPanel" configPanel.Size = UDim2.new(0, panelWidth, 1, -60) configPanel.Position = UDim2.fromOffset(contentBasePosX + panelWidth + panelGap, 10) configPanel.BackgroundColor3 = Color3.fromRGB(255, 255, 255) configPanel.BackgroundTransparency = 0.6 configPanel.BorderSizePixel = 0 configPanel.Visible = false configPanel.Parent = mainFrame Instance.new("UICorner", configPanel).CornerRadius = UDim.new(0, 8) local configTitle = Instance.new("TextLabel") configTitle.Size = UDim2.new(1, -12, 0, 28) configTitle.Position = UDim2.fromOffset(6, 8) configTitle.BackgroundTransparency = 1 configTitle.Text = "Config" configTitle.TextColor3 = Color3.fromRGB(100, 100, 100) configTitle.Font = Enum.Font.GothamSemibold configTitle.TextSize = 14 configTitle.TextXAlignment = Enum.TextXAlignment.Left configTitle.Parent = configPanel -- Main Content local content = Instance.new("Frame") content.Name = "Content" content.Size = UDim2.new(1, -(contentBasePosX + 20), 1, -60) content.Position = UDim2.fromOffset(contentBasePosX, 10) content.BackgroundTransparency = 1 content.Parent = mainFrame local title = Instance.new("TextLabel") title.Size = UDim2.new(1, -20, 0, 32) title.Position = UDim2.fromOffset(0, 0) title.BackgroundTransparency = 1 title.Text = "Remote Looper" title.TextColor3 = Color3.fromRGB(50, 50, 50) title.Font = Enum.Font.GothamBold title.TextSize = 18 title.TextXAlignment = Enum.TextXAlignment.Left title.Parent = content local statsBtn = Instance.new("TextButton") statsBtn.Size = UDim2.fromOffset(80, 32) statsBtn.Position = UDim2.fromOffset(0, 40) statsBtn.BackgroundColor3 = Color3.fromRGB(245, 245, 245) statsBtn.Text = "Stats" statsBtn.TextColor3 = Color3.fromRGB(100, 100, 100) statsBtn.Font = Enum.Font.GothamMedium statsBtn.TextSize = 14 statsBtn.AutoButtonColor = false statsBtn.Parent = content Instance.new("UICorner", statsBtn).CornerRadius = UDim.new(0, 6) statsBtn.MouseEnter:Connect(function() TweenService:Create(statsBtn, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(230, 230, 230)}):Play() end) statsBtn.MouseLeave:Connect(function() TweenService:Create(statsBtn, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(245, 245, 245)}):Play() end) -- Delay local delaySection = Instance.new("Frame") delaySection.Size = UDim2.new(1, 0, 0, 40) delaySection.Position = UDim2.fromOffset(0, 80) delaySection.BackgroundTransparency = 1 delaySection.Parent = content local delayLabel = Instance.new("TextLabel") delayLabel.Size = UDim2.fromOffset(120, 24) delayLabel.Position = UDim2.new(0, 0) delayLabel.BackgroundTransparency = 1 delayLabel.Text = "Delay (sec):" delayLabel.TextColor3 = Color3.fromRGB(100, 100, 105) delayLabel.Font = Enum.Font.GothamMedium delayLabel.TextSize = 14 delayLabel.TextXAlignment = Enum.TextXAlignment.Left delayLabel.Parent = delaySection local delayBox = Instance.new("TextBox") delayBox.Size = UDim2.fromOffset(80, 32) delayBox.Position = UDim2.fromOffset(120, 0) delayBox.BackgroundColor3 = Color3.fromRGB(245, 245, 245) delayBox.Text = "0.10" delayBox.TextColor3 = Color3.fromRGB(50, 50, 50) delayBox.Font = Enum.Font.Gotham delayBox.TextSize = 14 delayBox.ClearTextOnFocus = false delayBox.PlaceholderText = "0.10" delayBox.Parent = delaySection Instance.new("UICorner", delayBox).CornerRadius = UDim.new(0, 6) Instance.new("UIPadding", delayBox).PaddingLeft = UDim.new(0, 12) Instance.new("UIPadding", delayBox).PaddingRight = UDim.new(0, 12) -- Start/Stop local startStop = Instance.new("TextButton") startStop.Size = UDim2.fromOffset(120, 40) startStop.Position = UDim2.fromOffset(0, 130) startStop.BackgroundColor3 = Color3.fromRGB(34, 197, 94) startStop.Text = "Start" startStop.TextColor3 = Color3.fromRGB(255, 255, 255) startStop.Font = Enum.Font.GothamSemibold startStop.TextSize = 16 startStop.AutoButtonColor = false startStop.Parent = content Instance.new("UICorner", startStop).CornerRadius = UDim.new(0, 8) Instance.new("UIPadding", startStop).PaddingLeft = UDim.new(0, 20) Instance.new("UIPadding", startStop).PaddingRight = UDim.new(0, 20) local statusSection = Instance.new("Frame") statusSection.Size = UDim2.new(1, 0, 0, 30) statusSection.Position = UDim2.fromOffset(0, 180) statusSection.BackgroundTransparency = 1 statusSection.Parent = content local status = Instance.new("TextLabel") status.Size = UDim2.new(1, -130, 1, 0) status.BackgroundTransparency = 1 status.Text = "Status: idle | Remotes: None" status.TextColor3 = Color3.fromRGB(100, 100, 105) status.Font = Enum.Font.Gotham status.TextSize = 14 status.TextXAlignment = Enum.TextXAlignment.Left status.Parent = statusSection local sent = Instance.new("TextLabel") sent.Size = UDim2.fromOffset(120, 20) sent.Position = UDim2.new(1, -130, 0, 0) sent.BackgroundTransparency = 1 sent.Text = "Sent: 0" sent.TextColor3 = Color3.fromRGB(100, 100, 105) sent.Font = Enum.Font.GothamMedium sent.TextSize = 14 sent.TextXAlignment = Enum.TextXAlignment.Right sent.Parent = statusSection -- Sidebar Selected List local selectedList = Instance.new("ScrollingFrame") selectedList.Size = UDim2.new(1, -12, 1, -40) selectedList.Position = UDim2.fromOffset(6, 36) selectedList.BackgroundTransparency = 1 selectedList.BorderSizePixel = 0 selectedList.ScrollBarThickness = 4 selectedList.ScrollBarImageColor3 = Color3.fromRGB(200, 200, 200) selectedList.Parent = sidebar local selectedListLayout = Instance.new("UIListLayout") selectedListLayout.SortOrder = Enum.SortOrder.Name selectedListLayout.Padding = UDim.new(0, 2) selectedListLayout.Parent = selectedList --===================== -- STATE + FORWARD DECLS --===================== local running = false local totalSent = 0 local selected = {} -- { [remoteName] = bool } local statsOptions = {} -- { [remoteName] = {opt, check, label} } local configState = { -- per-remote config values SeedCollect = { amount = 1 }, -- default GrassCollect = { -- defaults (as requested: normal starts at 1) normal = 1, ruby = 0, silver = 0, golden = 0, diamond = 0 } } local updateSelectedList local updateUI local createStatsList local showConfigFor local updateLayout --===================== -- Layout updater --===================== updateLayout = function() local extra = 0 if statsPanel.Visible then extra = extra + (panelWidth + panelGap) end if configPanel.Visible then extra = extra + (panelWidth + panelGap) end local targetWidth = baseWidth + extra local targetContentX = contentBasePosX + extra local targetContentOffsetX = -(contentBasePosX + extra + 20) TweenService:Create(mainFrame, TweenInfo.new(0.25, Enum.EasingStyle.Quart), {Size = UDim2.fromOffset(targetWidth, mainFrame.Size.Y.Offset)}):Play() TweenService:Create(content, TweenInfo.new(0.25, Enum.EasingStyle.Quart), { Position = UDim2.fromOffset(targetContentX, content.Position.Y.Offset), Size = UDim2.new(1, targetContentOffsetX, 1, -60) }):Play() end --===================== -- Config panel builder --===================== local function clearChildren(parent) for _, c in ipairs(parent:GetChildren()) do if c:IsA("GuiObject") and c ~= configTitle then c:Destroy() end end end showConfigFor = function(remoteName) clearChildren(configPanel) configTitle.Text = "Config: " .. remoteName local function mkNumRow(y, labelText, startValue) local lbl = Instance.new("TextLabel") lbl.Size = UDim2.new(1, -12, 0, 24) lbl.Position = UDim2.fromOffset(6, y) lbl.BackgroundTransparency = 1 lbl.Text = labelText lbl.TextColor3 = Color3.fromRGB(100, 100, 100) lbl.Font = Enum.Font.Gotham lbl.TextSize = 14 lbl.TextXAlignment = Enum.TextXAlignment.Left lbl.Parent = configPanel local box = Instance.new("TextBox") box.Size = UDim2.fromOffset(110, 28) box.Position = UDim2.fromOffset(6, y + 22) box.BackgroundColor3 = Color3.fromRGB(245, 245, 245) box.Text = tostring(startValue or 0) box.TextColor3 = Color3.fromRGB(50, 50, 50) box.Font = Enum.Font.Gotham box.TextSize = 14 box.ClearTextOnFocus = false box.PlaceholderText = "0" box.Parent = configPanel Instance.new("UICorner", box).CornerRadius = UDim.new(0, 6) Instance.new("UIPadding", box).PaddingLeft = UDim.new(0, 10) Instance.new("UIPadding", box).PaddingRight = UDim.new(0, 10) return box end if remoteName == "SeedCollect" then local amountBox = mkNumRow(40, "Amount:", configState.SeedCollect.amount or 1) local saveBtn = Instance.new("TextButton") saveBtn.Size = UDim2.fromOffset(80, 32) saveBtn.Position = UDim2.fromOffset(6, 108) saveBtn.BackgroundColor3 = Color3.fromRGB(34, 197, 94) saveBtn.Text = "Save" saveBtn.TextColor3 = Color3.fromRGB(255, 255, 255) saveBtn.Font = Enum.Font.GothamSemibold saveBtn.TextSize = 14 saveBtn.AutoButtonColor = false saveBtn.Parent = configPanel Instance.new("UICorner", saveBtn).CornerRadius = UDim.new(0, 6) saveBtn.Activated:Connect(function() local n = tonumber(amountBox.Text) if not n or n < 0 then n = 0 end n = math.floor(n + 0.5) configState.SeedCollect.amount = n TweenService:Create(saveBtn, TweenInfo.new(0.08), {BackgroundColor3 = Color3.fromRGB(16, 185, 129)}):Play() task.delay(0.10, function() TweenService:Create(saveBtn, TweenInfo.new(0.12), {BackgroundColor3 = Color3.fromRGB(34, 197, 94)}):Play() configPanel.Visible = false updateLayout() end) end) elseif remoteName == "GrassCollect" then -- five fields: normal, ruby, silver, golden, diamond local gc = configState.GrassCollect local y = 40 local spacing = 48 local normalBox = mkNumRow(y + spacing*0, "normal:", gc.normal or 1) local rubyBox = mkNumRow(y + spacing*1, "ruby:", gc.ruby or 0) local silverBox = mkNumRow(y + spacing*2, "silver:", gc.silver or 0) local goldenBox = mkNumRow(y + spacing*3, "golden:", gc.golden or 0) local diamondBox = mkNumRow(y + spacing*4, "diamond:", gc.diamond or 0) local saveBtn = Instance.new("TextButton") saveBtn.Size = UDim2.fromOffset(80, 32) saveBtn.Position = UDim2.fromOffset(6, y + spacing*5 + 4) saveBtn.BackgroundColor3 = Color3.fromRGB(34, 197, 94) saveBtn.Text = "Save" saveBtn.TextColor3 = Color3.fromRGB(255, 255, 255) saveBtn.Font = Enum.Font.GothamSemibold saveBtn.TextSize = 14 saveBtn.AutoButtonColor = false saveBtn.Parent = configPanel Instance.new("UICorner", saveBtn).CornerRadius = UDim.new(0, 6) saveBtn.Activated:Connect(function() local function toNonNegInt(s) local v = tonumber(s) or 0 if v < 0 then v = 0 end return math.floor(v + 0.5) end gc.normal = toNonNegInt(normalBox.Text) gc.ruby = toNonNegInt(rubyBox.Text) gc.silver = toNonNegInt(silverBox.Text) gc.golden = toNonNegInt(goldenBox.Text) gc.diamond = toNonNegInt(diamondBox.Text) -- feedback then auto-close TweenService:Create(saveBtn, TweenInfo.new(0.08), {BackgroundColor3 = Color3.fromRGB(16, 185, 129)}):Play() task.delay(0.10, function() TweenService:Create(saveBtn, TweenInfo.new(0.12), {BackgroundColor3 = Color3.fromRGB(34, 197, 94)}):Play() configPanel.Visible = false updateLayout() end) end) else local info = Instance.new("TextLabel") info.Size = UDim2.new(1, -12, 0, 24) info.Position = UDim2.fromOffset(6, 40) info.BackgroundTransparency = 1 info.Text = "No configurable options." info.TextColor3 = Color3.fromRGB(120, 120, 120) info.Font = Enum.Font.Gotham info.TextSize = 14 info.TextXAlignment = Enum.TextXAlignment.Left info.Parent = configPanel end configPanel.Visible = true updateLayout() end --===================== -- Dynamic Stats List Creation --===================== createStatsList = function() for _, child in ipairs(statsList:GetChildren()) do if child:IsA("Frame") then child:Destroy() end end statsOptions = {} local filteredRemotes = {} local searchText = string.lower(searchBox.Text) for _, name in ipairs(knownRemotes) do if searchText == "" or string.find(string.lower(name), searchText) then table.insert(filteredRemotes, name) end end table.sort(filteredRemotes) for i, name in ipairs(filteredRemotes) do local container = Instance.new("Frame") container.Size = UDim2.new(1, 0, 0, 32) container.BackgroundTransparency = 1 container.LayoutOrder = i container.Parent = statsList local opt = Instance.new("TextButton") opt.Size = UDim2.new(1, 0, 1, 0) opt.BackgroundColor3 = Color3.fromRGB(245, 245, 245) opt.Text = "" opt.AutoButtonColor = false opt.Parent = container Instance.new("UICorner", opt).CornerRadius = UDim.new(0, 4) local check = Instance.new("TextLabel") check.Size = UDim2.fromOffset(20, 20) check.Position = UDim2.fromOffset(8, 6) check.BackgroundTransparency = 1 check.Text = "✓" check.TextColor3 = Color3.fromRGB(34, 197, 94) check.Font = Enum.Font.GothamBold check.TextSize = 14 check.Visible = selected[name] or false check.Parent = opt local label = Instance.new("TextLabel") label.Size = UDim2.new(1, -40, 1, 0) label.Position = UDim2.fromOffset(28, 0) label.BackgroundTransparency = 1 label.Text = name label.TextColor3 = selected[name] and Color3.fromRGB(34, 197, 94) or Color3.fromRGB(50, 50, 50) label.Font = Enum.Font.Gotham label.TextSize = 12 label.TextXAlignment = Enum.TextXAlignment.Left label.Parent = opt opt.MouseEnter:Connect(function() if not selected[name] then TweenService:Create(opt, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(230, 230, 230)}):Play() end end) opt.MouseLeave:Connect(function() if not selected[name] then TweenService:Create(opt, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(245, 245, 245)}):Play() end end) statsOptions[name] = {opt = opt, check = check, label = label} opt.Activated:Connect(function() selected[name] = not selected[name] check.Visible = selected[name] local labelColor = selected[name] and Color3.fromRGB(34, 197, 94) or Color3.fromRGB(50, 50, 50) local optColor = selected[name] and Color3.fromRGB(230, 245, 230) or Color3.fromRGB(245, 245, 245) TweenService:Create(opt, TweenInfo.new(0.1), {BackgroundColor3 = optColor}):Play() TweenService:Create(label, TweenInfo.new(0.1), {TextColor3 = labelColor}):Play() -- open config for configurable remotes if name == "SeedCollect" or name == "GrassCollect" then if not statsPanel.Visible then statsPanel.Visible = true end showConfigFor(name) end updateSelectedList() updateUI() end) end statsList.CanvasSize = UDim2.new(0, 0, 0, #filteredRemotes * 36) end --===================== -- Selected List Update --===================== updateSelectedList = function() for _, child in ipairs(selectedList:GetChildren()) do if child:IsA("Frame") then child:Destroy() end end local count = 0 local sortedSelected = {} for name, sel in pairs(selected) do if sel then table.insert(sortedSelected, name) end end table.sort(sortedSelected) for _, name in ipairs(sortedSelected) do count += 1 local container = Instance.new("Frame") container.Size = UDim2.new(1, 0, 0, 28) container.BackgroundTransparency = 1 container.LayoutOrder = count container.Parent = selectedList local label = Instance.new("TextLabel") label.Size = UDim2.new(1, 0, 1, 0) label.BackgroundTransparency = 1 label.Text = name label.TextColor3 = Color3.fromRGB(100, 100, 105) label.Font = Enum.Font.Gotham label.TextSize = 12 label.TextXAlignment = Enum.TextXAlignment.Left label.Parent = container Instance.new("UIPadding", label).PaddingLeft = UDim.new(0, 8) local removeBtn = Instance.new("TextButton") removeBtn.Size = UDim2.fromOffset(20, 20) removeBtn.Position = UDim2.new(1, -25, 0.5, -10) removeBtn.BackgroundTransparency = 1 removeBtn.Text = "×" removeBtn.TextColor3 = Color3.fromRGB(200, 100, 100) removeBtn.Font = Enum.Font.GothamBold removeBtn.TextSize = 14 removeBtn.AutoButtonColor = false removeBtn.Parent = container removeBtn.Activated:Connect(function() selected[name] = false if statsOptions[name] then statsOptions[name].check.Visible = false TweenService:Create(statsOptions[name].opt, TweenInfo.new(0.1), {BackgroundColor3 = Color3.fromRGB(245, 245, 245)}):Play() TweenService:Create(statsOptions[name].label, TweenInfo.new(0.1), {TextColor3 = Color3.fromRGB(50, 50, 50)}):Play() end updateSelectedList() updateUI() end) end selectedList.CanvasSize = UDim2.new(0, 0, 0, count * 30) end --===================== -- Non-Sticky Drag --===================== local dragBar = Instance.new("Frame") dragBar.Name = "DragBar" dragBar.Size = UDim2.new(1, 0, 0, 40) dragBar.BackgroundTransparency = 1 dragBar.Active = true dragBar.Parent = mainFrame local dragging = false local dragStart local startPos local dragInput local function updateDrag(input) local delta = input.Position - dragStart mainFrame.Position = UDim2.new( startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y ) end dragBar.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = mainFrame.Position end end) dragBar.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) UserInputService.InputChanged:Connect(function(input) if dragging and input == dragInput then updateDrag(input) end end) UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false dragInput = nil end end) --===================== -- Logic --===================== local function getDelay() local n = tonumber(delayBox.Text) if not n or n < 0 then n = 0 end if n < 0.02 then n = 0.02 end return n end local function getSelectedList() local list = {} for name, sel in pairs(selected) do if sel then table.insert(list, name) end end return list end updateUI = function() local selectedListLocal = getSelectedList() local remotesStr = #selectedListLocal > 0 and table.concat(selectedListLocal, ", ") or "None" status.Text = ("Status: %s | Remotes: %s"):format(running and "running" or "idle", remotesStr) sent.Text = "Sent: " .. totalSent local btnColor = running and Color3.fromRGB(239, 68, 68) or Color3.fromRGB(34, 197, 94) TweenService:Create(startStop, TweenInfo.new(0.2), {BackgroundColor3 = btnColor}):Play() end local function getArgsForRemote(name) if name == "IncreaseSilver" then return {1} elseif name == "SeedCollect" then local amount = configState.SeedCollect and tonumber(configState.SeedCollect.amount) or 1 if not amount or amount < 0 then amount = 0 end amount = math.floor(amount + 0.5) return { { amount = amount } } elseif name == "GrassCollect" then local g = configState.GrassCollect or {} local function normInt(v) v = tonumber(v) or 0; if v < 0 then v = 0 end; return math.floor(v + 0.5) end return { { normal = normInt(g.normal or 1), ruby = normInt(g.ruby or 0), silver = normInt(g.silver or 0), golden = normInt(g.golden or 0), diamond = normInt(g.diamond or 0), } } elseif name == "IncreasePop" then return {true} else return {} end end local function fireOnce() local cycleSent = 0 local hasError = false local errMsg = "" for name, _ in pairs(selected) do if selected[name] then local re = RemotesFolder:FindFirstChild(name) if re and re:IsA("RemoteEvent") then local args = getArgsForRemote(name) local ok, err = pcall(function() re:FireServer(unpack(args)) end) if ok then cycleSent += 1 else hasError = true errMsg = tostring(err) warn("Error firing " .. name .. ": " .. errMsg) end else warn("Remote not found: " .. name) end end end totalSent += cycleSent if hasError then status.Text = ("Status: error (%s)"):format(errMsg) end end local function startLoop() if running then return end local selectedListLocal = getSelectedList() if #selectedListLocal == 0 then status.Text = "Status: no remotes selected" return end running = true updateUI() task.spawn(function() while running do local ok, err = pcall(fireOnce) if not ok then status.Text = ("Status: error (%s)"):format(tostring(err)) end if running then updateUI() end task.wait(getDelay()) end end) end local function stopLoop() running = false updateUI() end --===================== -- Events --===================== closeBtn.Activated:Connect(function() stopLoop() sg:Destroy() end) statsBtn.Activated:Connect(function() statsPanel.Visible = not statsPanel.Visible if not statsPanel.Visible then configPanel.Visible = false end updateLayout() statsBtn.Text = statsPanel.Visible and "Close Stats" or "Stats" end) startStop.Activated:Connect(function() if running then stopLoop() else startLoop() end end) searchBox:GetPropertyChangedSignal("Text"):Connect(function() createStatsList() end) delayBox.FocusLost:Connect(updateUI) -- Hotkeys UserInputService.InputBegan:Connect(function(input, gpe) if gpe then return end if input.KeyCode == Enum.KeyCode.RightShift then sg.Enabled = not sg.Enabled elseif input.KeyCode == Enum.KeyCode.LeftControl and running then stopLoop() end end) --===================== -- Initial setup --===================== createStatsList() -- Default selected local defaultRemotes = {"IncreaseTree", "IncreaseSilver", "IncreaseMuscle"} for _, name in ipairs(defaultRemotes) do selected[name] = true end -- Reflect defaults if stats options exist for _, name in ipairs(defaultRemotes) do if statsOptions[name] then statsOptions[name].check.Visible = true statsOptions[name].label.TextColor3 = Color3.fromRGB(34, 197, 94) statsOptions[name].opt.BackgroundColor3 = Color3.fromRGB(230, 245, 230) end end updateSelectedList() updateUI()