"Terrain health"

Making a tool that can mine terrain is simple (usually). But the way all people execute on this doesn’t take to consideration that different materials are more difficult to mine away!

There might be a solution to this and I’m thinking its going to have to use “ReplaceMaterial” but there’s two problems with this: region3 is a cube, not a cylinder or sphere and how do I know how much health a specific part of the terrain has?

No topics are currently asking this so, yeah… Comment if you know how I can do this

2 Likes

I do think you would have to mine areas in squares or cylinders. To check how much health a terrain spot has, when the player mines the ground, you could round that position, and send it into a table. Then, if a player hits again in that 1X1X1 area, you could lower the “Health” of that table item, and if it reaches zero, remove the terrain from that position. Or course, you may want to make the areas a bit bigger, like 3X3X3. Make sense?

1 Like

I see what you mean, I’ll play around with that idea and update you with the results! (can take a bit)

Well… how do I detect the material of the terrain now?

Are you using the .Touched event?

Nevermind! Fixed it, I was just not using the right variable :sweat_smile:

The resolution of the terrain is so low that I can’t do this : ( GAH

I’m not sure what the terrain resolution has to do with anything.

When I replace the material with air you can set the resolution to 1,2,3 or 4. I use 4 but even then it just doesn’t want to replace the material, it works sometimes but sometimes not and when it works the “chunks” that I’m removing are huge

I have one last option, see if it works.

Yippi! I did it : D

There are 3 scripts involved but this script is most important

local Points = {} -- A value inside is going to look like {Vector3, Health, Material}
local Settings = require(script.Parent.Settings)
local Res = 1 -- 1 stud Res
local Hit = Vector3.new()

local function Dig(At)
	local Point = Instance.new("Attachment")
	local Effect = script.DigSmoke:Clone()
	Point.WorldPosition = At
	Effect.Parent = Point
	Effect.Enabled = true
	Point.Parent = game.Workspace.Terrain
	game:GetService("Debris"):AddItem(Point,2)
end

local function PlayAnimation()
	local Animation = Instance.new("Animation", script.Parent.Parent)
	Animation.AnimationId = script["Dig/Attack"].AnimationId
	local Play = script.Parent.Parent.Humanoid:LoadAnimation(Animation)
	Play:Play()
end

script.Parent.Activated:Connect(function()
	
	PlayAnimation()
	
	Hit = Vector3.new()
	
	script.RemoteEvent:FireAllClients()
	repeat wait() until Hit ~= Vector3.new()
	
	local From = Hit
	
	local Part, Pos, norm, TERRAINMATERIAL = game.Workspace:FindPartOnRay(Ray.new(Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) + Vector3.new(0,Res/2,Res/2), Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) - Vector3.new(0,Res/2,Res/2)))
	if Part ~= game.Workspace.Terrain then
		Part, Pos, norm, TERRAINMATERIAL = game.Workspace:FindPartOnRay(Ray.new(Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) + Vector3.new(Res/2,Res/2,0), Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) - Vector3.new(Res/2,Res/2,0)))
	end
	if Part ~= game.Workspace.Terrain then
		Part, Pos, norm, TERRAINMATERIAL = game.Workspace:FindPartOnRay(Ray.new(Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) + Vector3.new(-Res/2,Res/2,0), Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) - Vector3.new(-Res/2,Res/2,0)))
	end
	if Part ~= game.Workspace.Terrain then
		Part, Pos, norm, TERRAINMATERIAL = game.Workspace:FindPartOnRay(Ray.new(Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) + Vector3.new(0,Res/2,-Res/2), Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) - Vector3.new(0,Res/2,-Res/2)))
	end
	
	if Part == game.Workspace.Terrain then
		local DoesExist = false
		for Point = 1, #Points do
			if Points[Point][1] == Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res) then
				DoesExist = true
			end
		end
					
		if not DoesExist then
						
			local DecidedHealth = nil
			
			if TERRAINMATERIAL.Name == "Ground" then
				DecidedHealth = 5
			end	
			table.insert(Points, {Vector3.new(math.round(From.X/Res)*Res, math.round(From.Y/Res)*Res, math.round(From.Z/Res)*Res), DecidedHealth, TERRAINMATERIAL})
		end
		-- Time to damage or erase this terrain!
		local Remove = {} -- list for known destroyed points
		if Part == game.Workspace.Terrain then
			script.Parent.Handle.Dig:Play()
			script.Parent.Enabled = false
			for Point = 1, #Points do
				if (From - Points[Point][1]).Magnitude < Res then -- Its close enough
					Points[Point][2] -= Settings.TerrainDamage
					if Points[Point][2] <= 0 then -- DIE
						game.Workspace.Terrain:FillBall(From, 
								Settings.DigSize, 
								Enum.Material.Air
						)
						table.insert(Remove, Points[Point])
						Dig(Points[Point][1])
					end
				end
			end	
			-- If any points where destroyed we remove them!
			
			local RemoveS = {} -- list for unknown destroyed points around the known destroyed points
			for Point = 1, #Points do
				for Removing = 1, #Remove do
					if (Remove[Removing][1] - Points[Point][1]).Magnitude < Settings.DigSize-Res then -- This voxel is in mid air
						table.insert(RemoveS, Points[Point])
					end
				end
			end	
			for ILIMENATE = 1, #RemoveS do
				if table.find(Points,RemoveS[ILIMENATE]) then
					table.remove(Points, table.find(Points,RemoveS[ILIMENATE]))
				end
			end
			wait(Settings.Cooldown)
			script.Parent.Enabled = true
		end
	end
end)

script.RemoteEvent.OnServerEvent:Connect(function(Player,Pos)
	Hit = Pos
end)

The remote event is used to gather the mouse position and there is a module script called settings there I get other values from, the dig size should be 5.5.

If you’d like you can add more if statements to add more materials but this should give you an idea on how this should be approached.

Although there is a catch… Having two different materials next to each other means that this script can accidentally mine a weaker/stronger material even tho the played mined another material, just don’t make the layers of materials to small!

Thank you PiercedMissile for the help and goodnight because I have to sleep for once!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.