Issue with automatic turret

Hello everyone.

  1. What do you want to achieve?
    I am trying to create an automatic turret that shoots the player that enters its zone.
  2. What is the issue?
  • After messing around with my code I found out that if you spam going in and out a few times the turret will continue to shoot at your player even though you have already left the zone.

  • I feel the code itself could have been done a lot easier or have a lot part that are unnecessary, but I could not figure out anything else to do.

  1. What solutions have you tried so far?
  • I have tried my best debugging the issue but could not figure out a way to solve the problem completely.

  • The problem seems to be because targets[hit.Parent] becomes “CanBeShot” while the player has already left and since the script is delayed when checking for debounce to become true again, once it has become true the script continues and targets[hit.Parent] becomes true and the turret will start shooting at the player who has already left. (Not 100% sure if this is the problem)

local zone = script.Parent
local targets = {}

local rayParm = RaycastParams.new()
rayParm.IgnoreWater = true
rayParm.FilterType = Enum.RaycastFilterType.Blacklist
rayParm.FilterDescendantsInstances = {workspace.RedCrystal}

local function StartDamage(hit)
	if hit.Name == "HumanoidRootPart" then
		if targets[hit.Parent] == nil then
			targets[hit.Parent] = true
			targets[tostring(hit.Parent) .. "1"] = true
		end
				
		if targets[tostring(hit.Parent) .. "1"] == false then
			targets[tostring(hit.Parent) .. "1"] = "Loading"
			while targets[tostring(hit.Parent) .. "1"] == "Loading" do
				wait(.1)
				if targets[tostring(hit.Parent) .. "1"] == true then
					break
				end
			end
		end
		
		if targets[tostring(hit.Parent) .. "1"] == true then
			targets[tostring(hit.Parent) .. "1"] = false
			if targets[hit.Parent] == "CanBeShot" then
				targets[hit.Parent] = true
			elseif targets[hit.Parent] == "Left" then
				while targets[hit.Parent] == "Left" do
					wait(.1)
					if targets[hit.Parent] == "CanBeShot" then
						targets[hit.Parent] = true
						break
					end
				end
			end
		end
		
		while targets[hit.Parent] == true and hit.Name == "HumanoidRootPart" do
			targets[hit.Parent] = false
			local distance = (workspace.RedCrystal.core.Position - hit.Position).Magnitude
			local bullet = Instance.new("Part")
			bullet.Size = Vector3.new(0 , 0 , distance)
			bullet.CFrame = CFrame.new(workspace.RedCrystal.core.Position , hit.Position) * CFrame.new(0 , 0 , -distance/2)
			bullet.Parent = workspace
			bullet.Anchored = true
			bullet.CanCollide = false
		
			hit.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
			wait(.5)
				
			bullet:Destroy()
			
			wait(2)
			
			targets[tostring(hit.Parent) .. "1"] = true
			
			if targets[hit.Parent] ~= "Left" then
				targets[hit.Parent] = true
			elseif targets[hit.Parent] == "Left" then
				targets[hit.Parent] = "CanBeShot"
				
			end
		end
	end
end

zone.Touched:Connect(StartDamage)

zone.TouchEnded:Connect(function(hit)
	if hit.Name == "HumanoidRootPart" then
		targets[hit.Parent] = "Left"
		
	end
end)
  • targets[hit.Parent] is suppose to check and act as a cooldown for when the turret can shoot again.

  • targets[tostring(hit.Parent) … “1”] is suppose to be a personal debounce for each player to make sure they don’t spam the touch function

Hopefully I have explained everything clearly enough. I am still quite new at scripting so I am hoping someone can teach me how to write better and clearer scripts here so I can improve.

Thank you! :grinning::+1:

1 Like