
Key Required VerifiedUniversal

--[[
WARNING: Heads up! This script has not been verified by ScriptBlox. Use at your own risk!
]]
local Client = require(game.Players.LocalPlayer.PlayerScripts.Client)
local player = game.Players.LocalPlayer
local config = {
plantDelay = 1,
plantAmount = 3,
surroundBase = false,
spiralBase = false,
circleRadius = 45,
skyBase = false,
heartBase = false,
pyramidBase = false, -- Added Pyramid Base
}
local SKY_HEIGHT = 50 -- Fixed height for Sky Base
-- GUI setup
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "SaplingPlanterUI"
screenGui.ResetOnSpawn = false
screenGui.Parent = player.PlayerGui
-- Main frame
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0, 280, 0, 400)
frame.Position = UDim2.new(0.5, -140, 0.5, -200)
frame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
frame.BorderSizePixel = 0
frame.Parent = screenGui
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 12)
corner.Parent = frame
-- Title
local title = Instance.new("TextLabel")
title.Size = UDim2.new(1, 0, 0, 36)
title.Position = UDim2.new(0, 0, 0, 0)
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
-- Owner Label
local ownerLabel = Instance.new("TextLabel")
ownerLabel.Size = UDim2.new(1, 0, 0, 24)
ownerLabel.Position = UDim2.new(0, 0, 0, 36)
ownerLabel.BackgroundTransparency = 1
ownerLabel.Text = "Owner: joshe454"
ownerLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
ownerLabel.TextSize = 14
ownerLabel.Font = Enum.Font.Gotham
ownerLabel.TextXAlignment = Enum.TextXAlignment.Center
ownerLabel.Parent = frame
-- Dragging Logic
local dragging, dragInput, dragStart, startPos = false, nil, nil, nil
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)
-- Scrolling frame
local scroll = Instance.new("ScrollingFrame")
scroll.Size = UDim2.new(1, 0, 1, -70)
scroll.Position = UDim2.new(0, 0, 0, 36)
scroll.BackgroundTransparency = 1
scroll.CanvasSize = UDim2.new(0,0,1.5,0)
scroll.ScrollBarThickness = 6
scroll.Parent = frame
-- GUI Utilities
local function createToggle(name, posY, colorOff)
local btn = Instance.new("TextButton")
btn.Size = UDim2.new(1,-20,0,32)
btn.Position = UDim2.new(0,10,0,posY)
btn.BackgroundColor3 = colorOff
btn.Text = name .. ": OFF"
btn.TextColor3 = Color3.fromRGB(255,255,255)
btn.TextSize = 14
btn.Font = Enum.Font.GothamBold
btn.Parent = scroll
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0,6)
corner.Parent = btn
return btn
end
local function createLabel(text,posY)
local lbl = Instance.new("TextLabel")
lbl.Size = UDim2.new(1,-20,0,22)
lbl.Position = UDim2.new(0,10,0,posY)
lbl.BackgroundTransparency = 1
lbl.Text = text
lbl.TextColor3 = Color3.fromRGB(255,255,255)
lbl.TextSize = 14
lbl.Font = Enum.Font.Gotham
lbl.TextXAlignment = Enum.TextXAlignment.Left
lbl.Parent = scroll
return lbl
end
local function createTextBox(text,posY,placeholder)
local tb = Instance.new("TextBox")
tb.Size = UDim2.new(1,-20,0,30)
tb.Position = UDim2.new(0,10,0,posY)
tb.BackgroundColor3 = Color3.fromRGB(50,50,50)
tb.Text = text
tb.TextColor3 = Color3.fromRGB(255,255,255)
tb.TextSize = 14
tb.Font = Enum.Font.Gotham
tb.PlaceholderText = placeholder
tb.Parent = scroll
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0,6)
corner.Parent = tb
return tb
end
-- Input fields
local delayLabel = createLabel("Plant Delay: 1s",10)
local delayInput = createTextBox("1",32,"0-2 seconds")
local amountLabel = createLabel("Plant Amount: 3",70)
local amountInput = createTextBox("3",92,"1-1000")
local radiusLabel = createLabel("Base Radius: 45",130)
local radiusInput = createTextBox("45",152,"41-100 studs")
-- Toggle buttons
local surroundToggle = createToggle("Surround Base",190, Color3.fromRGB(60,60,60))
local spiralToggle = createToggle("Spiral Base",230, Color3.fromRGB(60,60,60))
local skyToggle = createToggle("Sky Base",270, Color3.fromRGB(60,60,60))
local heartToggle = createToggle("Heart Base",310, Color3.fromRGB(60,60,60))
local pyramidToggle = createToggle("Pyramid Base",350, Color3.fromRGB(60,60,60)) -- Added toggle
-- Input handling
delayInput.FocusLost:Connect(function()
local v = tonumber(delayInput.Text)
if v and v>=0 and v<=2 then
config.plantDelay=v
delayLabel.Text="Plant Delay: "..v.."s"
else delayInput.Text=tostring(config.plantDelay) end
end)
amountInput.FocusLost:Connect(function()
local v = tonumber(amountInput.Text)
if v and v>=1 and v<=1000 then
config.plantAmount = math.floor(v)
amountLabel.Text = "Plant Amount: "..v
else amountInput.Text=tostring(config.plantAmount) end
end)
radiusInput.FocusLost:Connect(function()
local v = tonumber(radiusInput.Text)
if v and v>=41 and v<=100 then
config.circleRadius=v
radiusLabel.Text="Base Radius: "..v
else radiusInput.Text=tostring(config.circleRadius) end
end)
-- Toggle logic
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)
else
surroundToggle.Text = "Surround Base: OFF"
surroundToggle.BackgroundColor3 = Color3.fromRGB(60,60,60)
end
end)
spiralToggle.MouseButton1Click:Connect(function()
config.spiralBase = not config.spiralBase
if config.spiralBase then
spiralToggle.Text = "Spiral Base: ON"
spiralToggle.BackgroundColor3 = Color3.fromRGB(255,120,0)
else
spiralToggle.Text = "Spiral Base: OFF"
spiralToggle.BackgroundColor3 = Color3.fromRGB(60,60,60)
end
end)
skyToggle.MouseButton1Click:Connect(function()
config.skyBase = not config.skyBase
if config.skyBase then
skyToggle.Text = "Sky Base: ON"
skyToggle.BackgroundColor3 = Color3.fromRGB(0,170,255)
else
skyToggle.Text = "Sky Base: OFF"
skyToggle.BackgroundColor3 = Color3.fromRGB(60,60,60)
end
end)
heartToggle.MouseButton1Click:Connect(function()
config.heartBase = not config.heartBase
if config.heartBase then
heartToggle.Text = "Heart Base: ON"
heartToggle.BackgroundColor3 = Color3.fromRGB(255,0,100)
else
heartToggle.Text = "Heart Base: OFF"
heartToggle.BackgroundColor3 = Color3.fromRGB(60,60,60)
end
end)
pyramidToggle.MouseButton1Click:Connect(function()
config.pyramidBase = not config.pyramidBase
if config.pyramidBase then
pyramidToggle.Text = "Pyramid Base: ON"
pyramidToggle.BackgroundColor3 = Color3.fromRGB(255,215,0)
else
pyramidToggle.Text = "Pyramid Base: OFF"
pyramidToggle.BackgroundColor3 = Color3.fromRGB(60,60,60)
end
end)
-- ====================
-- Base Generators & Planting
-- ====================
local previewParts={}
local function clearPreview()
for _,p in ipairs(previewParts) do
if p and p.Parent then p:Destroy() end
end
previewParts={}
end
local function findNearestSapling()
local char = player.Character
if not char or not char.PrimaryPart then return nil end
local pos = char.PrimaryPart.Position
local nearest, shortest = nil, math.huge
for _,item in ipairs(workspace.Items:GetChildren()) do
if item.Name=="Sapling" and item.PrimaryPart then
local dist = (item.PrimaryPart.Position-pos).Magnitude
if dist<shortest then
nearest=item
shortest=dist
end
end
end
return nearest
end
local function getCampfirePosition()
if workspace.Map.Campground.MainFire.PrimaryPart then
return workspace.Map.Campground.MainFire.PrimaryPart.Position
end
return nil
end
local function getPlantPosition(basePos)
if config.skyBase then
return Vector3.new(basePos.X, SKY_HEIGHT, basePos.Z)
else
local ray = RaycastParams.new()
ray.FilterDescendantsInstances = {workspace.Map.Ground, workspace.Map:FindFirstChild("Snow")}
ray.FilterType = Enum.RaycastFilterType.Include
ray.IgnoreWater=true
local result = workspace:Raycast(basePos, Vector3.new(0,-55,0), ray)
if result then return result.Position end
return nil
end
end
-- Remote capture
local capturedArgs, capturedRemote=nil,nil
local originalInvokeServer = Client.Events.RequestPlantItem.InvokeServer
Client.Events.RequestPlantItem.InvokeServer = function(self,...)
local args={...}
capturedArgs=args
capturedRemote=self
return originalInvokeServer(self,...)
end
-- Base generators
local function getHeartPositions(center, scale, saplingCount)
local positions = {}
for i = 0, saplingCount - 1 do
local t = (i / saplingCount) * math.pi * 2
local x = 16 * math.sin(t)^3
local y = 13 * math.cos(t) - 5*math.cos(2*t) - 2*math.cos(3*t) - math.cos(4*t)
local posX = center.X + x * scale
local posZ = center.Z + y * scale
local posY = config.skyBase and SKY_HEIGHT or center.Y + 0.5
table.insert(positions, Vector3.new(posX, posY, posZ))
end
return positions
end
local function getCirclePositions(center, radius, count)
local positions = {}
for i = 0, count - 1 do
local angle = (i / count) * math.pi * 2
local x = center.X + math.cos(angle) * radius
local z = center.Z + math.sin(angle) * radius
local y = config.skyBase and SKY_HEIGHT or center.Y + 0.5
table.insert(positions, Vector3.new(x, y, z))
end
return positions
end
local function getSpiralPositions(center, radius, count)
local positions = {}
local turns = 3
for i = 1, count do
local t = i / count * math.pi * 2 * turns
local r = (i / count) * radius
local x = center.X + math.cos(t) * r
local z = center.Z + math.sin(t) * r
local y = config.skyBase and SKY_HEIGHT or center.Y + 0.5
table.insert(positions, Vector3.new(x, y, z))
end
return positions
end
local function getSkyFloorPositions(center, radius, gridSize)
local positions = {}
local step = (radius * 2) / (gridSize - 1)
for i = 0, gridSize - 1 do
for j = 0, gridSize - 1 do
local x = center.X - radius + i * step
local z = center.Z - radius + j * step
local y = SKY_HEIGHT
table.insert(positions, Vector3.new(x, y, z))
end
end
return positions
end
local function getPyramidPositions(center, baseRadius, layers)
local positions = {}
for y = 0, layers-1 do
local radius = baseRadius * (1 - y / layers)
local count = math.max(1, math.floor(radius * 6))
for i = 0, count-1 do
local angle = (i / count) * math.pi * 2
local x = center.X + math.cos(angle) * radius
local z = center.Z + math.sin(angle) * radius
local posY = config.skyBase and SKY_HEIGHT or center.Y + 0.5 + y
table.insert(positions, Vector3.new(x, posY, z))
end
end
return positions
end
-- Preview
local function showPreview()
clearPreview()
local campfirePos = getCampfirePosition()
if not campfirePos then return end
local positions={}
if config.pyramidBase then
positions = getPyramidPositions(campfirePos, config.circleRadius, math.ceil(config.plantAmount/10))
elseif config.heartBase then
positions = getHeartPositions(campfirePos, config.circleRadius/25, config.plantAmount)
elseif config.skyBase then
positions = getSkyFloorPositions(campfirePos, config.circleRadius, 4)
elseif config.spiralBase then
positions = getSpiralPositions(campfirePos, config.circleRadius, config.plantAmount)
elseif config.surroundBase then
positions = getCirclePositions(campfirePos, config.circleRadius, config.plantAmount)
else
local item = findNearestSapling()
if not item or not item.PrimaryPart then return end
local pos = getPlantPosition(item.PrimaryPart.Position)
if pos then table.insert(positions,pos) end
end
for _,pos in ipairs(positions) do
local part = Instance.new("Part")
part.Size = Vector3.new(2,0.5,2)
part.Position = pos
part.Anchored = true
part.CanCollide = false
part.Transparency = 0.5
part.Material = Enum.Material.Neon
part.Color = Color3.fromRGB(255,0,100)
part.Parent = workspace
table.insert(previewParts, part)
end
end
-- Plant
local function plantSapling()
clearPreview()
local item = findNearestSapling()
if not item or not item.PrimaryPart then return end
local campfirePos = getCampfirePosition()
if not campfirePos then return end
local positions={}
if config.pyramidBase then
positions = getPyramidPositions(campfirePos, config.circleRadius, math.ceil(config.plantAmount/10))
elseif config.heartBase then
positions = getHeartPositions(campfirePos, config.circleRadius/25, config.plantAmount)
elseif config.skyBase then
positions = getSkyFloorPositions(campfirePos, config.circleRadius, 4)
elseif config.spiralBase then
positions = getSpiralPositions(campfirePos, config.circleRadius, config.plantAmount)
elseif config.surroundBase then
positions = getCirclePositions(campfirePos, config.circleRadius, config.plantAmount)
else
local pos = getPlantPosition(item.PrimaryPart.Position)
if pos then table.insert(positions,pos) end
end
if #positions==0 then return end
item.Parent = game.ReplicatedStorage.TempStorage
local result = Client.Events.RequestPlantItem:InvokeServer(item, positions[1])
if not result or not result.Success then return end
task.spawn(function()
if capturedArgs and capturedRemote then
for i=2,#positions do
task.wait(config.plantDelay)
capturedArgs[2] = positions[i]
capturedRemote:InvokeServer(unpack(capturedArgs))
end
end
end)
end
-- Buttons
local previewButton = Instance.new("TextButton")
previewButton.Size = UDim2.new(0.48,0,0,36)
previewButton.Position = UDim2.new(0,10,1,-50)
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,36)
plantButton.Position = UDim2.new(0.52,0,1,-50)
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 plantCorner = Instance.new("UICorner")
plantCorner.CornerRadius = UDim.new(0,6)
plantCorner.Parent = plantButton
previewButton.MouseButton1Click:Connect(showPreview)
plantButton.MouseButton1Click:Connect(plantSapling)
-- ===== Minimize Button =====
local minimizeBtn = Instance.new("TextButton")
minimizeBtn.Size = UDim2.new(0, 24, 0, 24)
minimizeBtn.Position = UDim2.new(1, -28, 0, 6)
minimizeBtn.BackgroundColor3 = Color3.fromRGB(200, 50, 50)
minimizeBtn.Text = "X"
minimizeBtn.TextColor3 = Color3.fromRGB(255,255,255)
minimizeBtn.TextSize = 18
minimizeBtn.Font = Enum.Font.GothamBold
minimizeBtn.Parent = frame
local minCorner = Instance.new("UICorner")
minCorner.CornerRadius = UDim.new(0,4)
minCorner.Parent = minimizeBtn
local minimized = false
minimizeBtn.MouseButton1Click:Connect(function()
minimized = not minimized
scroll.Visible = not minimized
previewButton.Visible = not minimized
plantButton.Visible = not minimized
frame.Size = minimized and UDim2.new(0,280,0,60) or UDim2.new(0,280,0,400)
end)



New updates coming it would be an Pyramid and other types of fixes comment below for ideas (:
@joshe454 any way to minimize the window so you able to at the base with the base preview of the design!!:) other then that script is fire
Working on it right now
@joshe454 sweet🫡
No ?
Update guys minimize button
Pyramid has been added
doesnt work on xeno and doesnt have a start button
does it work
how to use?