Remote Menu
Key Required

Remote Menu

[🌱] Grass Incremental Simulatorkrittapun2070krittapun2070 3.7K views 239 executesUpdated Oct 9, 2025
Unrated
00
Lua Script•846 lines (29678 chars)
-- 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()

Features & Information

Just figure it out btw: grass can only be set just one to 999 and the rest need to be 0, seeds can set to unlimited

Community Comments (0)

No comments yet for this script.

More Scripts for [🌱] Grass Incremental Simulator