CCCPaste

Satisfying part tweening

-- // Satisfying part tweening by yite_mc \\


local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--local remotes = ReplicatedStorage:WaitForChild("Remotes")
--local modifyRemote = remotes:WaitForChild("Modify")


local fieldSize = 35
local radius = 16
local partHeight = 5
local lerpSpeed = 0.5

local defaultNoiseScale = 0.1 
local defaultHeightMultiplier = 20 
local defaultSeed = 50 

local originalHeights = {}

-- Generates a hill like field using parts with a noise-based heightmap. Adjusting the noiseScale and heightMultiplier can create different terrains
local function generateField(noiseScale, heightMultiplier, seed)
	for i, v in pairs(workspace.Field:GetChildren()) do
		v:Destroy()
	end
	for x = -fieldSize, fieldSize do
		for z = -fieldSize, fieldSize do
			local part = Instance.new("Part")
			part.Size = Vector3.new(1, partHeight, 1)
			local noiseValue = math.clamp(math.noise(x * (noiseScale or defaultNoiseScale), z * (noiseScale or defaultNoiseScale), seed or defaultSeed), 0, math.huge)
			local hillHeight = noiseValue * (heightMultiplier or defaultHeightMultiplier)

			part.Position = Vector3.new(x, hillHeight, z)
			part.Anchored = true
			part.Color = Color3.new(0, 0, 0)
			part.Parent = workspace.Field

			originalHeights[part] = hillHeight	
		end
		task.wait(0.00001)
	end
end

-- Smoothly animate the parts based on the player's distance from them
game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local hrp: BasePart = character:WaitForChild("HumanoidRootPart")

		RunService.Heartbeat:Connect(function()
			for _, v in pairs(workspace.Field:GetChildren()) do
				if v:IsA("BasePart") then
					local distance = (v.Position - hrp.Position).Magnitude
					local progress = 0

					if distance <= radius then
						-- If the player is within the radius, smoothly interpolate between the base height and the target height, looks better with HSV (imo)
						progress = 1 - (distance / radius)

						local hue = (distance / radius) % 1  
						local color = Color3.fromHSV(hue, hue, hue)

						v.Color = color
					else
						v.Color = Color3.new(0, 0, 0)
					end


					local baseY = originalHeights[v]
					local targetY = baseY - (progress * partHeight)
					local currentPos = v.Position
					local targetPos = Vector3.new(currentPos.X, targetY, currentPos.Z)

					v.Position = currentPos:Lerp(targetPos, lerpSpeed)
				end
			end
		end)
	end)
end)

generateField()

-- Optional remote event to modify the field
--[[modifyRemote.OnServerEvent:Connect(function(player, inputs)
	generateField(inputs.Scale, inputs.HeightMultiplier, inputs.Seed)
end)]]