local Client = require(game.Players.LocalPlayer.PlayerScripts.Client) local player = game.Players.LocalPlayer local config = { plantDelay = 1, plantAmount = 3, surroundBase = false, circleRadius = 45 } local screenGui = Instance.new("ScreenGui") screenGui.Name = "SaplingPlanterUI" screenGui.ResetOnSpawn = false screenGui.Parent = player.PlayerGui local frame = Instance.new("Frame") frame.Size = UDim2.new(0, 320, 0, 400) frame.Position = UDim2.new(0.5, -160, 0.5, -200) frame.BackgroundColor3 = Color3.fromRGB(40, 40, 40) frame.BorderSizePixel = 2 frame.BorderColor3 = Color3.fromRGB(80, 80, 80) frame.Parent = screenGui local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 8) corner.Parent = frame local title = Instance.new("TextLabel") title.Size = UDim2.new(1, 0, 0, 40) title.BackgroundTransparency = 1 title.Text = "infinite saplings ;)" title.TextColor3 = Color3.fromRGB(255, 255, 255) title.TextSize = 20 title.Font = Enum.Font.GothamBold title.Parent = frame local usageLabel = Instance.new("TextLabel") usageLabel.Size = UDim2.new(1, -20, 0, 25) usageLabel.Position = UDim2.new(0, 10, 0, 45) usageLabel.BackgroundTransparency = 1 usageLabel.Text = "Plant saplings. Discord - heyboysb" usageLabel.TextColor3 = Color3.fromRGB(200, 200, 200) usageLabel.TextSize = 13 usageLabel.Font = Enum.Font.Gotham usageLabel.TextXAlignment = Enum.TextXAlignment.Left usageLabel.Parent = frame local delayLabel = Instance.new("TextLabel") delayLabel.Size = UDim2.new(1, -20, 0, 25) delayLabel.Position = UDim2.new(0, 10, 0, 85) delayLabel.BackgroundTransparency = 1 delayLabel.Text = "Plant Delay: 1s" delayLabel.TextColor3 = Color3.fromRGB(255, 255, 255) delayLabel.TextSize = 14 delayLabel.Font = Enum.Font.Gotham delayLabel.TextXAlignment = Enum.TextXAlignment.Left delayLabel.Parent = frame local delaySlider = Instance.new("TextBox") delaySlider.Size = UDim2.new(1, -20, 0, 35) delaySlider.Position = UDim2.new(0, 10, 0, 110) delaySlider.BackgroundColor3 = Color3.fromRGB(60, 60, 60) delaySlider.Text = "1" delaySlider.TextColor3 = Color3.fromRGB(255, 255, 255) delaySlider.TextSize = 14 delaySlider.Font = Enum.Font.Gotham delaySlider.PlaceholderText = "0-2 seconds" delaySlider.Parent = frame local delayCorner = Instance.new("UICorner") delayCorner.CornerRadius = UDim.new(0, 4) delayCorner.Parent = delaySlider local amountLabel = Instance.new("TextLabel") amountLabel.Size = UDim2.new(1, -20, 0, 25) amountLabel.Position = UDim2.new(0, 10, 0, 160) amountLabel.BackgroundTransparency = 1 amountLabel.Text = "Plant Amount: 3" amountLabel.TextColor3 = Color3.fromRGB(255, 255, 255) amountLabel.TextSize = 14 amountLabel.Font = Enum.Font.Gotham amountLabel.TextXAlignment = Enum.TextXAlignment.Left amountLabel.Parent = frame local amountInput = Instance.new("TextBox") amountInput.Size = UDim2.new(1, -20, 0, 35) amountInput.Position = UDim2.new(0, 10, 0, 185) amountInput.BackgroundColor3 = Color3.fromRGB(60, 60, 60) amountInput.Text = "3" amountInput.TextColor3 = Color3.fromRGB(255, 255, 255) amountInput.TextSize = 14 amountInput.Font = Enum.Font.Gotham amountInput.PlaceholderText = "1-1000" amountInput.Parent = frame local amountCorner = Instance.new("UICorner") amountCorner.CornerRadius = UDim.new(0, 4) amountCorner.Parent = amountInput local surroundToggle = Instance.new("TextButton") surroundToggle.Size = UDim2.new(1, -20, 0, 35) surroundToggle.Position = UDim2.new(0, 10, 0, 235) surroundToggle.BackgroundColor3 = Color3.fromRGB(60, 60, 60) surroundToggle.Text = "Surround Base: OFF" surroundToggle.TextColor3 = Color3.fromRGB(255, 255, 255) surroundToggle.TextSize = 14 surroundToggle.Font = Enum.Font.GothamBold surroundToggle.Parent = frame local surroundToggleCorner = Instance.new("UICorner") surroundToggleCorner.CornerRadius = UDim.new(0, 4) surroundToggleCorner.Parent = surroundToggle local radiusLabel = Instance.new("TextLabel") radiusLabel.Size = UDim2.new(1, -20, 0, 25) radiusLabel.Position = UDim2.new(0, 10, 0, 280) radiusLabel.BackgroundTransparency = 1 radiusLabel.Text = "Base Radius: 45" radiusLabel.TextColor3 = Color3.fromRGB(200, 200, 200) radiusLabel.TextSize = 14 radiusLabel.Font = Enum.Font.Gotham radiusLabel.TextXAlignment = Enum.TextXAlignment.Left radiusLabel.Visible = false radiusLabel.Parent = frame local radiusInput = Instance.new("TextBox") radiusInput.Size = UDim2.new(1, -20, 0, 35) radiusInput.Position = UDim2.new(0, 10, 0, 305) radiusInput.BackgroundColor3 = Color3.fromRGB(60, 60, 60) radiusInput.Text = "45" radiusInput.TextColor3 = Color3.fromRGB(255, 255, 255) radiusInput.TextSize = 14 radiusInput.Font = Enum.Font.Gotham radiusInput.PlaceholderText = "41-100 studs" radiusInput.Visible = false radiusInput.Parent = frame local radiusCorner = Instance.new("UICorner") radiusCorner.CornerRadius = UDim.new(0, 4) radiusCorner.Parent = radiusInput local previewButton = Instance.new("TextButton") previewButton.Size = UDim2.new(0.48, 0, 0, 40) previewButton.Position = UDim2.new(0, 10, 0, 350) previewButton.BackgroundColor3 = Color3.fromRGB(0, 120, 200) previewButton.Text = "Preview" previewButton.TextColor3 = Color3.fromRGB(255, 255, 255) previewButton.TextSize = 16 previewButton.Font = Enum.Font.GothamBold previewButton.Parent = frame local previewCorner = Instance.new("UICorner") previewCorner.CornerRadius = UDim.new(0, 6) previewCorner.Parent = previewButton local plantButton = Instance.new("TextButton") plantButton.Size = UDim2.new(0.48, 0, 0, 40) plantButton.Position = UDim2.new(0.52, 0, 0, 350) plantButton.BackgroundColor3 = Color3.fromRGB(0, 170, 0) plantButton.Text = "Plant" plantButton.TextColor3 = Color3.fromRGB(255, 255, 255) plantButton.TextSize = 16 plantButton.Font = Enum.Font.GothamBold plantButton.Parent = frame local buttonCorner = Instance.new("UICorner") buttonCorner.CornerRadius = UDim.new(0, 6) buttonCorner.Parent = plantButton local dragging = false local dragInput, dragStart, startPos local function update(input) local delta = input.Position - dragStart frame.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) end frame.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = frame.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragging = false end end) end end) frame.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) game:GetService("UserInputService").InputChanged:Connect(function(input) if input == dragInput and dragging then update(input) end end) surroundToggle.MouseButton1Click:Connect(function() config.surroundBase = not config.surroundBase if config.surroundBase then surroundToggle.Text = "Surround Base: ON" surroundToggle.BackgroundColor3 = Color3.fromRGB(0, 170, 0) radiusLabel.Visible = true radiusInput.Visible = true else surroundToggle.Text = "Surround Base: OFF" surroundToggle.BackgroundColor3 = Color3.fromRGB(60, 60, 60) radiusLabel.Visible = false radiusInput.Visible = false end end) radiusInput.FocusLost:Connect(function() local value = tonumber(radiusInput.Text) if value and value >= 41 and value <= 100 then config.circleRadius = value radiusLabel.Text = "Base Radius: " .. value else radiusInput.Text = tostring(config.circleRadius) end end) delaySlider.FocusLost:Connect(function() local value = tonumber(delaySlider.Text) if value and value >= 0 and value <= 2 then config.plantDelay = value delayLabel.Text = "Plant Delay: " .. value .. "s" else delaySlider.Text = tostring(config.plantDelay) end end) amountInput.FocusLost:Connect(function() local value = tonumber(amountInput.Text) if value and value >= 1 and value <= 1000 then config.plantAmount = math.floor(value) amountLabel.Text = "Plant Amount: " .. config.plantAmount amountInput.Text = tostring(config.plantAmount) else amountInput.Text = tostring(config.plantAmount) end end) local function findNearestSapling() local character = player.Character if not character or not character.PrimaryPart then return nil end local playerPosition = character.PrimaryPart.Position local nearestSapling = nil local shortestDistance = math.huge for _, item in ipairs(workspace.Items:GetChildren()) do if item.Name == "Sapling" and item.PrimaryPart then local distance = (item.PrimaryPart.Position - playerPosition).Magnitude if distance < shortestDistance then shortestDistance = distance nearestSapling = item end end end return nearestSapling end local function FindGrassBlock(position) local raycastParams = RaycastParams.new() raycastParams.FilterDescendantsInstances = {workspace.Map.Ground, workspace.Map:FindFirstChild("Snow")} raycastParams.FilterType = Enum.RaycastFilterType.Include raycastParams.IgnoreWater = true local raycastResult = workspace:Raycast(position, Vector3.new(0, -55, 0), raycastParams) if raycastResult then return raycastResult.Position end return nil end local function getCirclePositions(centerPosition, radius, count) local positions = {} local angleStep = (2 * math.pi) / count for i = 0, count - 1 do local angle = i * angleStep local x = centerPosition.X + radius * math.cos(angle) local z = centerPosition.Z + radius * math.sin(angle) local position = Vector3.new(x, centerPosition.Y + 10, z) local groundPos = FindGrassBlock(position) if groundPos then table.insert(positions, groundPos) end end return positions end local function getCampfirePosition() if workspace.Map.Campground.MainFire.PrimaryPart then return workspace.Map.Campground.MainFire.PrimaryPart.Position end return nil end local previewParts = {} local function clearPreview() for _, part in ipairs(previewParts) do if part and part.Parent then part:Destroy() end end previewParts = {} end local function showPreview() clearPreview() local campfirePos = getCampfirePosition() if not campfirePos then return end if config.surroundBase then local circlePositions = getCirclePositions(campfirePos, config.circleRadius, config.plantAmount) for i, position in ipairs(circlePositions) do local previewPart = Instance.new("Part") previewPart.Size = Vector3.new(2, 0.5, 2) previewPart.Position = position + Vector3.new(0, 0.5, 0) previewPart.Anchored = true previewPart.CanCollide = false previewPart.Transparency = 0.5 previewPart.Material = Enum.Material.Neon previewPart.Color = Color3.fromRGB(0, 255, 0) previewPart.Parent = workspace table.insert(previewParts, previewPart) end else local targetItem = findNearestSapling() if not targetItem or not targetItem.PrimaryPart then return end local groundPosition = FindGrassBlock(targetItem.PrimaryPart.Position) if not groundPosition then return end local centerPreview = Instance.new("Part") centerPreview.Size = Vector3.new(2, 0.5, 2) centerPreview.Position = groundPosition + Vector3.new(0, 0.5, 0) centerPreview.Anchored = true centerPreview.CanCollide = false centerPreview.Transparency = 0.5 centerPreview.Material = Enum.Material.Neon local distance = (campfirePos - groundPosition).Magnitude centerPreview.Color = distance < 40 and Color3.fromRGB(255, 0, 0) or Color3.fromRGB(0, 255, 0) centerPreview.Parent = workspace table.insert(previewParts, centerPreview) for i = 1, math.min(config.plantAmount - 1, 5) do local previewPart = Instance.new("Part") previewPart.Size = Vector3.new(2, 0.5, 2) previewPart.Position = groundPosition + Vector3.new(0, 0.5 + (i * 0.3), 0) previewPart.Anchored = true previewPart.CanCollide = false previewPart.Transparency = 0.5 + (i * 0.08) previewPart.Material = Enum.Material.Neon previewPart.Color = distance < 40 and Color3.fromRGB(255, 0, 0) or Color3.fromRGB(0, 255, 0) previewPart.Parent = workspace table.insert(previewParts, previewPart) end end task.delay(10, clearPreview) end local capturedArgs = nil local capturedRemote = nil local originalInvokeServer = Client.Events.RequestPlantItem.InvokeServer Client.Events.RequestPlantItem.InvokeServer = function(self, ...) local args = {...} capturedArgs = args capturedRemote = self return originalInvokeServer(self, ...) end local function plantSapling() clearPreview() local targetItem = findNearestSapling() if not targetItem or not targetItem.PrimaryPart then return end local campfirePos = getCampfirePosition() if not campfirePos then return end if config.surroundBase then local circlePositions = getCirclePositions(campfirePos, config.circleRadius, config.plantAmount) if #circlePositions == 0 then return end targetItem.Parent = game.ReplicatedStorage.TempStorage local originalParent = targetItem.Parent local result = Client.Events.RequestPlantItem:InvokeServer(targetItem, circlePositions[1]) if not result or not result.Success then targetItem.Parent = originalParent return end task.spawn(function() if capturedArgs and capturedRemote then for i = 2, #circlePositions do task.wait(config.plantDelay) capturedArgs[2] = circlePositions[i] capturedRemote:InvokeServer(unpack(capturedArgs)) end end end) else local groundPosition = FindGrassBlock(targetItem.PrimaryPart.Position) if not groundPosition then return end local distance = (campfirePos - groundPosition).Magnitude if distance < 40 then return end targetItem.Parent = game.ReplicatedStorage.TempStorage local originalParent = targetItem.Parent local result = Client.Events.RequestPlantItem:InvokeServer(targetItem, groundPosition) if not result or not result.Success then targetItem.Parent = originalParent return end task.spawn(function() if capturedArgs and capturedRemote then for i = 1, config.plantAmount - 1 do task.wait(config.plantDelay) capturedRemote:InvokeServer(unpack(capturedArgs)) end end end) end end previewButton.MouseButton1Click:Connect(showPreview) plantButton.MouseButton1Click:Connect(plantSapling)