Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- made by @RobeeSeth
- local basepart = script.Parent
- local resetpart = workspace:WaitForChild("reset")
- local gridsize = 1 -- 1 = 1 stud part, higher means it'd be more optimized, but less precise, since there'd be less parts to step on, I haven't messed with the larger ones since I added foot prints, so it might not work.
- local ogheight = 1.2 -- edit this if you want lower or higher snow.
- local minheight = 0
- local shrinkstep = 0.8 -- this is the tiny foot steps you leave behind.
- local neighborshrinkstep = 0.6 -- this is the rest of the snow that you step on.
- local cooldowntime = 0.35 -- cooldown before you can step on the same snow part again.
- local maxpushheight = ogheight + 0.3 -- so, when you step on snow, the snow around that part will get higher.
- local maxpushvary = 0.15
- local sizex = basepart.Size.X
- local sizez = basepart.Size.Z
- local basepos = basepart.Position
- local partsx = math.floor(sizex / gridsize)
- local partsz = math.floor(sizez / gridsize)
- local snowmodel = Instance.new("Model")
- snowmodel.Name = "snowgrid"
- snowmodel.Parent = workspace
- local snowgrid = {}
- local function setheight(part, newheight)
- part.Size = Vector3.new(part.Size.X, newheight, part.Size.Z)
- part.Position = Vector3.new(
- part.Position.X,
- basepart.Position.Y + basepart.Size.Y / 2 + newheight / 2,
- part.Position.Z
- )
- end
- local function shrinkbit(part, amount)
- local oldheight = part.Size.Y
- local newheight = math.max(oldheight - amount, minheight)
- if newheight ~= oldheight then
- setheight(part, newheight)
- end
- return oldheight - newheight
- end
- local function pushtop(part, amount)
- local newheight = math.min(part.Size.Y + amount, maxpushheight)
- if newheight ~= part.Size.Y then
- setheight(part, newheight)
- end
- end
- local function pushfullnbs(originx, originz, lostvolume)
- local nearby = {}
- for dx = -1, 1 do
- for dz = -1, 1 do
- if dx ~= 0 or dz ~= 0 then
- local nx, nz = originx + dx, originz + dz
- local neighbor = snowgrid[nx] and snowgrid[nx][nz]
- if neighbor and math.abs(neighbor.part.Size.Y - ogheight) < 0.01 then
- table.insert(nearby, neighbor.part)
- end
- end
- end
- end
- if #nearby > 0 then
- local pushper = lostvolume / #nearby
- for _, p in ipairs(nearby) do
- local randpush = math.random() * maxpushvary
- pushtop(p, pushper + randpush)
- end
- end
- end
- local function shrinknbs(originx, originz, shrinkamt)
- for dx = -1, 1 do
- for dz = -1, 1 do
- if dx ~= 0 or dz ~= 0 then
- local nx, nz = originx + dx, originz + dz
- local neighbor = snowgrid[nx] and snowgrid[nx][nz]
- if neighbor and tick() - neighbor.lastshrink > cooldowntime then
- local lost = shrinkbit(neighbor.part, shrinkamt)
- neighbor.lastshrink = tick()
- pushfullnbs(nx, nz, lost)
- end
- end
- end
- end
- end
- local function onstepped(part, x, z)
- return function(hit)
- if not hit:IsA("BasePart") then return end
- local data = snowgrid[x][z]
- if tick() - data.lastshrink < cooldowntime then return end
- local char = hit.Parent
- local isplayer = char and char:FindFirstChild("HumanoidRootPart")
- if isplayer then
- local lost = shrinkbit(part, shrinkstep)
- data.lastshrink = tick()
- shrinknbs(x, z, neighborshrinkstep)
- pushfullnbs(x, z, lost)
- else
- if hit.Anchored then return end
- local lost = shrinkbit(part, neighborshrinkstep)
- data.lastshrink = tick()
- shrinknbs(x, z, neighborshrinkstep)
- pushfullnbs(x, z, lost)
- end
- end
- end
- for x = 0, partsx - 1 do
- snowgrid[x] = {}
- for z = 0, partsz - 1 do
- local partsize = Vector3.new(gridsize, ogheight, gridsize)
- local partpos = Vector3.new(
- basepos.X - sizex / 2 + x * gridsize + gridsize / 2,
- basepos.Y + basepart.Size.Y / 2 + ogheight / 2,
- basepos.Z - sizez / 2 + z * gridsize + gridsize / 2
- )
- local regioncf = CFrame.new(partpos)
- local regionsize = partsize
- local overlap = OverlapParams.new()
- overlap.FilterType = Enum.RaycastFilterType.Exclude
- overlap.FilterDescendantsInstances = {basepart, snowmodel}
- overlap.CollisionGroup = "Default"
- local blocked = false
- local touching = workspace:GetPartBoundsInBox(regioncf, regionsize, overlap)
- for _, other in ipairs(touching) do
- if other:IsA("BasePart") and other.Anchored and other.Transparency < 1 and other.CanCollide then
- local pos, size = other.Position, other.Size
- if pos and size then
- local min = pos - size / 2
- local max = pos + size / 2
- if partpos.X >= min.X and partpos.X <= max.X and
- partpos.Y >= min.Y and partpos.Y <= max.Y and
- partpos.Z >= min.Z and partpos.Z <= max.Z then
- blocked = true
- break
- end
- end
- end
- end
- if not blocked then
- local part = Instance.new("Part")
- part.Size = partsize
- part.Position = partpos
- part.Anchored = true
- part.TopSurface = Enum.SurfaceType.Studs
- part.BottomSurface = Enum.SurfaceType.Smooth
- part.Color = Color3.fromRGB(255, 255, 255)
- part.Material = Enum.Material.Plastic
- part.CanCollide = false -- edit this if you want to collide with the snow, wouldn't recommend but go ahead.
- part.Parent = snowmodel
- snowgrid[x][z] = {
- part = part,
- lastshrink = 0
- }
- part.Touched:Connect(onstepped(part, x, z))
- end
- end
- end
- local function resetall()
- for x = 0, partsx - 1 do
- for z = 0, partsz - 1 do
- local pd = snowgrid[x][z]
- if pd then
- setheight(pd.part, ogheight)
- end
- end
- end
- end
- local click = resetpart:FindFirstChild("ClickDetector")
- if click then
- click.MouseClick:Connect(function()
- resetall()
- end)
- end
Advertisement
Add Comment
Please, Sign In to add comment