Scripting Landmine

I am trying to script a landmine so that when you walk on it the pressure pad goes down until it detects that the player has moved a certain distance then raises and explodes however I am trying to do this with a loop repeat task.wait() until and I am sure there must be a better way to accomplish this any help offered will be a big help, Thanks.

local s = script.Parent
Debounce = false

s.Touched:Connect(function(hit)
	
	local humanoid = hit.Parent:FindFirstChild("Humanoid")
	
	if humanoid ~= nil and Debounce == false then
		Debounce = true
		
		s.Click:Play()
		
		for i =  0,0.04,0.01 do
			
			s.CFrame = s.CFrame * CFrame.new(0,-i,0)
			task.wait(0.01)
			
			repeat task.wait() until humanoid.MoveDirection.Magnitude > 0.1 
				s.CFrame = s.CFrame * CFrame.new(0,i,0)
				task.wait(0.01)
		end
	end
end)

You can use an asynchronous thread using spawn to prevent interruptions or yielding to the for loop you have.

I would also recommend moving it outside of the for loop to prevent it from running twice.

1 Like

I have no clue what a asynchronous thread is.

You should also reset Debounce = false after the wait loop to keep the s.Touched function from firing every touch.

1 Like

I did this on purpose because i don’t want it to loop after the player moves because it will explode and be deleted from the game.

Asynchronous, or Async, is multithreading. It means different pieces of code are executed “at the same time” (Technically it isn’t, but it is in effect the same thing).

For example:

-- Non-async:
for i=1, math.huge do -- This will take a *very* long time to finish
	print("Loop")
end
warn("Done!")

The print after the loop will not print until the loop is completed. However, the following is a bit different:

-- Async:
coroutine.wrap(function()
	for i=1, math.huge do
		print("Loop")
	end
end)() -- Don't forget () to run it
warn("Done!")

The print after the loop will print together with the loop, as it is executed side-by-side.

This is however most likely not something you’d have any use of in this situation.

1 Like

Oh i know about coroutine.wraps(function() I just didn’t know the terminology, thanks for explaining.

1 Like

To answer your actual question, I’d probably use events instead. You could use .TouchEnded to detect when they leave the mine, and then trigger an explosion.

1 Like

How would i use this though, I tried it before but instead of returning to normal it created an elevator effect which made it continuously go up it was probably just an error in my code but i used Debounce so I’m not sure where I went wrong.

Heres the code.

local s = script.Parent
Debounce = false

s.Touched:Connect(function(hit)
	
	local humanoid = hit.Parent:FindFirstChild("Humanoid")
	
	if humanoid ~= nil and Debounce == false then
		Debounce = true
		
		s.Click:Play()
		s.CFrame = s.CFrame * CFrame.new(0,-.1,0)
		
		Debounce = false
		
		s.TouchEnded:Connect(function(ended)
			
			if humanoid ~= nil and Debounce == false then 
				Debounce = true
				
				s.Click:Play()
				s.CFrame = s.CFrame * CFrame.new(0,.1,0)
				
				Debounce = false
				
			end
		end)
	end
end)

Every time it is touched another function is connected up to TouchEnded, which I don’t think is really a good idea. This will cause multiple events to happen. I would have the connection already made before being touched, and add a variable to filter it.

You are not destroying the landmine, if you didn’t do this with your other approach then you would have a similar effect as well. But just as @SubtotalAnt8185 said, don’t create a new .TouchEnded for every .Touched. You don’t need a variable filter though, as .TouchEnded can’t fire unless .Touched has been fired.