Digging Terrain Feature Help

I am making a game where digging terrain is a large feature but I need to only be allowed to do it in a certain area to a certain depth. I wish to try using ‘plots’ of land also and that would mean having the shovel check if it is in the owner’s area possibly through a part collision as the whole map is terrain. But i havent yet reached the point of making the shovel damage the terrain yet.

Here is the script I am using, the output says that
“Torso is not a valid member of Model” on line: 167

wait(1)
enabled = true
Tool = script.Parent
down = false -- Mouse isn't down
gui = script.LoadBar:clone() -- Displays your process in digging

--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
--returns true if made a wedge, false if the cell remains a block
function MakeWedge(x, y, z, defaultmaterial)
	local c = game.Workspace.Terrain
	--gather info about all the cells around x, y, z
	surroundings = {} --surroundings is a 3 x 3 x 3 array of the material of the cells adjacent to x, y, z
	for i = x - 1, x + 1 do
		surroundings[i] = {}
		for j = y - 1, y + 1 do
			surroundings[i][j] = {}
			for k = z - 1, z + 1 do
				local material, wedge, rotation = c:GetCell(i, j, k)
				surroundings[i][j][k] = material.Value
			end
		end
	end
	--make some useful arrays and counters
	local sides = {} --sides is an array of the material of the 4 adjacent sides
	sides[0] = surroundings[x - 1][y][z]
	sides[1] = surroundings[x][y][z + 1]
	sides[2] = surroundings[x + 1][y][z]
	sides[3] = surroundings[x][y][z - 1]
	local adjacentSides = 0
	for n = 0, 3 do
		if sides[n] > 0 then
			adjacentSides = adjacentSides + 1
		end
	end
	local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
	sidesAbove[0] = surroundings[x - 1][y + 1][z]
	sidesAbove[1] = surroundings[x][y + 1][z + 1]
	sidesAbove[2] = surroundings[x + 1][y + 1][z]
	sidesAbove[3] = surroundings[x][y + 1][z - 1]
	local adjacentSidesAbove = 0
	for n = 0, 3 do
		if sidesAbove[n] > 0 then
			adjacentSidesAbove = adjacentSidesAbove + 1
		end
	end
	local corners = {} --corners is an array of the material of the 4 adjacent corners
	corners[0] = surroundings[x - 1][y][z - 1]
	corners[1] = surroundings[x - 1][y][z + 1]
	corners[2] = surroundings[x + 1][y][z + 1]
	corners[3] = surroundings[x + 1][y][z - 1]
	local adjacentCorners = 0
	for n = 0, 3 do
		if corners[n] > 0 then
			adjacentCorners = adjacentCorners + 1
		end
	end
	local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
	cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
	cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
	cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
	cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
	local adjacentCornersAbove = 0
	for n = 0, 3 do
		if cornersAbove[n] > 0 then
			adjacentCornersAbove = adjacentCornersAbove + 1
		end
	end
	--determine what type of wedge to make
	local material = nil
	local wedge = nil
	local rotation = nil 
	if defaultmaterial then
		material = defaultmaterial
	else
		material, wedge, rotation = c:GetCell(x, y, z) --start with the existing material, wedge, and rotation
	end
	wedge = 0 --default wedge is a block
	rotation = 0 --default rotation is 0
	--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
	if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
		if adjacentSides == 1 then
			for n = 0, 3 do
				if sides[n] > 0 then
					wedge = 1
					rotation = (n + 1) % 4
					c:SetCell(x, y, z, material, wedge, rotation)
					return true
				end
			end
		elseif  adjacentSides == 3 then
			for n = 0, 3 do
				if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
					wedge = 1
					rotation = (n + 2) % 4
					c:SetCell(x, y, z, material, wedge, rotation)
					return true
				end
			end
		end
	end
	--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
	if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
		for n = 0, 3 do
			if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
				wedge = 2
				rotation = (n + 2) % 4
				c:SetCell(x, y, z, material, wedge, rotation)
				return true
			end
		end
	end
	--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
	if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
		if adjacentCorners > 1 then
			for n = 0, 3 do
				if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then 
					wedge = 3
					rotation = (n + 3) % 4
					c:SetCell(x, y, z, material, wedge, rotation)
					return true
				end
			end
		end
	elseif adjacentSides == 4 and adjacentCorners == 3 then
		for n = 0, 3 do
			if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
				wedge = 3
				rotation = (n + 3) % 4
				c:SetCell(x, y, z, material, wedge, rotation)
				return true
			end
		end
	end
	--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
	if adjacentSides == 2 and adjacentCorners < 4 then
		for n = 0, 3 do
			if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
				wedge = 4
				rotation = n
				c:SetCell(x, y, z, material, wedge, rotation)
				return true
			end
		end
	end
	c:SetCell(x, y, z, material, wedge, rotation)
	return false
end

function updateMouseRadius(mouse) -- Makes sure that while the player is digging he doesn't go move his mouse somewhere else going outside our magnitude
p = game.Players.LocalPlayer
if (mouse.Hit.p - p.Character.Torso.Position).magnitude > 10 then -- YOU RULE BREAKER!!!
onDeselect() -- Acts as if they stopped holding the mouse down
end
end



function onClick(mouse)
	h = game.Players.LocalPlayer.Character.Humanoid
	if not enabled or down or h == nil then
		return
	end
		p = game.Players.LocalPlayer
		if (p == nil) then return end
		if (p.Character == nil) then return end
LINE 167 if (mouse.Hit.p - p.Character.Torso.Position).magnitude > 10 then return end 
		down = true
		enabled = false
		c = game.Workspace.Terrain
		while down do
			Tool.Dirt.Smoke.Enabled = true
			if not p.PlayerGui:findFirstChild("LoadBar") then
				local l = gui:clone()
				l.Parent = p.PlayerGui
				script.Parent.guiObject.Value = l
			end
			local guivalue = p.PlayerGui:findFirstChild("LoadBar").Frame.LoadBarPercentage
			updateMouseRadius(mouse) -- Checks radius
			guivalue.Value = guivalue.Value + 1
			if guivalue.Value >= 100 then
				local cellPos = c:WorldToCellPreferSolid(Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
				local x = cellPos.x
				local y = cellPos.y
				local z = cellPos.z		
				c:SetCell(x, y, z, 0, 0, 0)
				for i = x - 1, x + 1 do
					for j = y - 1, y + 1 do
						for k = z - 1, z + 1 do
							MakeWedge(i, j, k)
						end
					end
				end
				Tool.Dirt.Smoke.Enabled = false
				onDeselect(mouse) -- Kills GUI
				enabled = false
				mouse.Icon = "rbxasset://textures\\GunWaitCursor.png"
				wait(0.5)
				mouse.Icon = "rbxasset://textures\\GunCursor.png"
				enabled = true
			end
		wait()
		end
end

function onClickOff(mouse)
Tool.Dirt.Smoke.Enabled = false
enabled = true
down = false
	if script.Parent.guiObject.Value ~= nil then
		script.Parent.guiObject.Value:remove()
	end
	if Tool.DiggyDiggyHole.Value ~= nil then
		Tool.DiggyDiggyHole.Value:Stop()
		Tool.DiggyDiggyHole.Value:remove()
	end
	Tool.GripForward = Vector3.new(0,0,-1)
	Tool.GripRight = Vector3.new(0,0,0)
	Tool.GripUp = Vector3.new(0, 1, 0)
	Tool.Animate.Disabled = true -- The script seems to crash after digging due to the animation becoming nil. Just restart it.
	Tool.Animate.Disabled = false
end

function onDeselect(mouse)
Tool.Dirt.Smoke.Enabled = false
enabled = true
down = false
	if script.Parent.guiObject.Value ~= nil then
		script.Parent.guiObject.Value:remove()
	end
	if Tool.DiggyDiggyHole.Value ~= nil then
		Tool.DiggyDiggyHole.Value:Stop()
		Tool.DiggyDiggyHole.Value:remove()
	end
	Tool.GripForward = Vector3.new(0,0,-1)
	Tool.GripRight = Vector3.new(0,0,0)
	Tool.GripUp = Vector3.new(0, 1, 0)
	Tool.Animate.Disabled = true -- The script seems to crash after digging due to the animation becoming nil. Just restart it.
	Tool.Animate.Disabled = false
end

function onSelect(mouse)
		mouse.Icon = "rbxasset://textures\\GunCursor.png"
		mouse.Button1Down:connect(function () onClick(mouse) end)
		mouse.Button1Up:connect(function () onClickOff(mouse) end)
end



script.Parent.Equipped:connect(onSelect)
script.Parent.UnEquipped:connect(onDeselect)

Something possibly to do with this block:

function onClick(mouse)
	h = game.Players.LocalPlayer.Character.Humanoid
	if not enabled or down or h == nil then
		return
	end
		p = game.Players.LocalPlayer
		if (p == nil) then return end
		if (p.Character == nil) then return end
LINE 167	if (mouse.Hit.p - p.Character.Torso.Position).magnitude > 10 then return end
		down = true
		enabled = false
		c = game.Workspace.Terrain

I dont honestly know how to write one of these so i’m willing to answer unclear questions :slight_smile:

its not a valid member if you are using r15 instead just use HumanoidRootPart it is available for both r6 and r15 characters

1 Like

Awesome thanks ill give it a shot!

EDIT: It worked now I just need to implement a small explosion to damage the terrain thanks so much! :slight_smile: