Soo I Am Making Procedural Generation And IDK How Do I Stop The Rocks From Spawning On The Water
Module Script Called Chunk
local TERRAIN_HEIGHT_COLORS = { [-40] = Color3.fromRGB(216, 204, 157); [-50] = Color3.fromRGB(53, 53, 53); [-10] = Color3.fromRGB(72, 113, 58); [0] = Color3.fromRGB(56, 88, 45); [75] = Color3.fromRGB(96, 101, 108); } local X, Z = 4, 4 local WIDTH_SCALE = 15 local HEIGHT_SCALE = 200 local TERRAIN_SMOOTHNESS = 15 local MIN_TREE_SPAWN_HEIGHT = -15 local MAX_TREE_SPAWN_HEIGHT = 30 local TREE_DENSITY = 1 local ROCK_DENSITY = 2 local SEED = workspace.SEED.Value local wedge = Instance.new("WedgePart"); wedge.Anchored = true; wedge.TopSurface = Enum.SurfaceType.Smooth; wedge.BottomSurface = Enum.SurfaceType.Smooth; local function draw3dTriangle(a, b, c) local ab, ac, bc = b - a, c - a, c - b; local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc); if (abd > acd and abd > bcd) then c, a = a, c; elseif (acd > bcd and acd > abd) then a, b = b, a; end ab, ac, bc = b - a, c - a, c - b; local right = ac:Cross(ab).unit; local up = bc:Cross(right).unit; local back = bc.unit; local height = math.abs(ab:Dot(up)); local w1 = wedge:Clone(); w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back))); w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back); w1.Parent = workspace; local w2 = wedge:Clone(); w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back))); w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back); w2.Parent = workspace; return w1, w2; end local function getHeight(chunkPosX, chunkPosZ, x, z) local height = math.noise( (X/TERRAIN_SMOOTHNESS * chunkPosX) + x/TERRAIN_SMOOTHNESS, (Z/TERRAIN_SMOOTHNESS * chunkPosZ) + z/TERRAIN_SMOOTHNESS, SEED ) * HEIGHT_SCALE if height > 20 then local difference = height - 20 height += (difference * 1.2) end if height < -20 then local difference = height - -20 height += (difference * 1.2) end return height end local function getPosition(chunkPosX, chunkPosZ, x, z) return Vector3.new( chunkPosX*X*WIDTH_SCALE + x*WIDTH_SCALE, getHeight(chunkPosX, chunkPosZ, x, z), chunkPosZ*Z*WIDTH_SCALE + z*WIDTH_SCALE ) end local function paintWedge(wedge) local wedgeHeight = wedge.Position.Y local color local lowerColorHeight local higherColorHeight for height, heightColor in pairs(TERRAIN_HEIGHT_COLORS) do if wedgeHeight == height then color = heightColor break end if (wedgeHeight < height) and (not higherColorHeight or height < higherColorHeight) then higherColorHeight = height end if (wedgeHeight > height) and (not lowerColorHeight or height > lowerColorHeight) then lowerColorHeight = height end end if not color then if higherColorHeight == nil then color = TERRAIN_HEIGHT_COLORS[lowerColorHeight] elseif lowerColorHeight == nil then color = TERRAIN_HEIGHT_COLORS[higherColorHeight] else local alpha = (wedgeHeight - lowerColorHeight) / (higherColorHeight - lowerColorHeight) local lowerColor = TERRAIN_HEIGHT_COLORS[lowerColorHeight] local higherColor = TERRAIN_HEIGHT_COLORS[higherColorHeight] color = lowerColor:lerp(higherColor, alpha) end end wedge.Material = Enum.Material.Grass wedge.Color = color end local function addWater(chunk) local cframe = CFrame.new( (chunk.x + .5) * chunk.WIDTH_SIZE_X, -70, (chunk.z + .5) * chunk.WIDTH_SIZE_Z ) local size = Vector3.new( chunk.WIDTH_SIZE_X, 90, chunk.WIDTH_SIZE_Z ) workspace.Terrain:FillBlock(cframe, size, Enum.Material.Water) chunk.waterCFrame = cframe chunk.waterSize = size end local function addTrees(chunk) local posGrid = chunk.positionGrid local instances = chunk.instances local chunkPosX = chunk.x local chunkPosZ = chunk.z for x = 0, X-1 do for z = 0, Z-1 do local pos = posGrid[x][z] if pos.Y >= MIN_TREE_SPAWN_HEIGHT and pos.Y <= MAX_TREE_SPAWN_HEIGHT then math.randomseed(x * (chunkPosX+SEED) + z * (chunkPosZ+SEED)) if math.random(1,3) == TREE_DENSITY then local tree = game.ReplicatedStorage.Tree:Clone() for index, child in pairs(tree:GetChildren()) do if child.Name == "Leaf" then child.Color = Color3.fromRGB( 75 + math.random(-25, 25), 151 + math.random(-25, 25), 75 + math.random(-25, 25) ) end end local cframe = CFrame.new(pos) * CFrame.new( math.random() * math.random(-10, 10), 0, math.random() * math.random(-10, 10) ) * CFrame.Angles(0, 2 * math.pi * math.random(), 0) tree:SetPrimaryPartCFrame(cframe) tree.Parent = workspace table.insert(instances, tree) end end end end end local function addRocks(chunk) local rock = game.ReplicatedStorage.Rock:Clone() local posGrid = chunk.positionGrid local instances = chunk.instances local chunkPosX = chunk.x local chunkPosZ = chunk.z for x = 0, X-1 do for z = 0, Z-1 do local pos = posGrid[x][z] if pos.Y >= MIN_TREE_SPAWN_HEIGHT and pos.Y <= MAX_TREE_SPAWN_HEIGHT then math.randomseed(x * (chunkPosX+SEED) + z * (chunkPosZ+SEED)) if math.random(1,3) == ROCK_DENSITY then local cframe = CFrame.new(pos)* CFrame.new(math.random() * math.random(-20, 20),0,math.random() * math.random(-20, 120))* CFrame.Angles(0, 5 * math.pi * math.random(), 0) rock:SetPrimaryPartCFrame(cframe) rock.Parent = workspace table.insert(instances, rock) end end end end end local Chunk = {} Chunk.__index = Chunk Chunk.WIDTH_SIZE_X = X * WIDTH_SCALE Chunk.WIDTH_SIZE_Z = Z * WIDTH_SCALE function Chunk.new(chunkPosX, chunkPosZ) local chunk = { instances = {}; positionGrid = {}; x = chunkPosX; z = chunkPosZ; } setmetatable(chunk, Chunk) local positionGrid = chunk.positionGrid for x = 0, X do positionGrid[x] = {} for z = 0, Z do positionGrid[x][z] = getPosition(chunkPosX, chunkPosZ, x, z) end end for x = 0, X-1 do for z = 0, Z-1 do local a = positionGrid[x][z] local b = positionGrid[x+1][z] local c = positionGrid[x][z+1] local d = positionGrid[x+1][z+1] local wedgeA, wedgeB = draw3dTriangle(a, b, c) local wedgeC, wedgeD = draw3dTriangle(b, c, d) paintWedge(wedgeA) paintWedge(wedgeB) paintWedge(wedgeC) paintWedge(wedgeD) table.insert(chunk.instances, wedgeA) table.insert(chunk.instances, wedgeB) table.insert(chunk.instances, wedgeC) table.insert(chunk.instances, wedgeD) end end addWater(chunk) addTrees(chunk) addRocks(chunk) return chunk end function Chunk:Destroy() for index, instance in ipairs(self.instances) do instance:Destroy() end workspace.Terrain:FillBlock(self.waterCFrame, self.waterSize, Enum.Material.Air) end return Chunk