How do I get my Monster AI to keep attacking

  1. What do you want to achieve? Keep it simple and clear!

To fix an attack bug that can exploited in my monster AI

  1. What is the issue? Include screenshots / videos if possible!

So I have created a monster AI that I am really happy with. The only problem is that I’ve found you can avoid it from attacking you by standing still which I can see this being something players can exploit.

This bug has something to do with Touched:Connect() function but I’ve been struggling to find a solution.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I’ve tried looking up a solution as well as tried adding a while loop in the code block but I can’t seem to get the AI to attack after it has touched the player.

The example of the code is here and I will give a video example as well.

local attackDebounce = false
local Cooldown = 3

function attack()
	local connection
	
	connection = Head.Touched:Connect(function(hit)
		local targetDistance = (Head.Position - hit.Position).Magnitude
		while wait(Cooldown) do
			if not attackDebounce and targetDistance < 5 then
				if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 then
					attackDebounce = true
					Entity.Humanoid.WalkSpeed = Stopping
					Attack:Play()
					hit.Parent.Humanoid:TakeDamage(10)
					print("You've been hit")
					task.wait(1)
					Attack:Stop()
					Entity.Humanoid.WalkSpeed = Walkspeed
					task.spawn(function()
						task.wait(Cooldown)
						attackDebounce = false
					end)
				end
			else
				connection:Disconnect()
				break
			end
		end
		
	end)
end

Attack Error

2 Likes

I’m almost certain the problem here is that you’re disconnecting the function before it sets the walkspeed back.

But I gotta say, to fix this you basically have to rewrite your entire script, even beyond the attack function.

I would suggest connecting the .Touched event once instead of all the time.
Then you can simply return when your AI isn’t attacking.


Best regards,
Pinker

2 Likes

Instead of using .touched events, it’d be beneficial to use RaycastHitbox for this. And I recommend doing monster AI hitreg on the client, to have more accuracy (so the client can dodge with more consistency). But having it done on the client comes at the risk of exploiters if you don’t properly secure your remoteevents.

But the issue is with disconnecting the .touched event

3 Likes

I’ve rewritten the code a few times. I can see where you are coming from and see if it other issues in my whole code thought.

1 Like

Ah damn I think I will look into RaycastHitbox.

When it comes to the Disconnect line, should I take it out of the loop? Or is the disconnect even just going to keep this proble from happening?

1 Like

I think the loop is also part of the problem tbh. You don’t actually even need to loop at that point anymore.

But from what I’ve seen, you’re trying to make it attack in a radius. In that case you could use Workspace:GetPartsInRadius().


I’ve also rewritten your code a bit, although it isn’t finished or compatible with your existing other code.

But since i already have it written, I might as well post it here. Maybe it showcases some things that could help you.

Obviously in this unfinished version you can’t just call your attack function to make the AI attack, since it would infinitely connect.

local COOLDOWN = 3
local NEXT_ATTACK_TIME = 0

local function increaseCooldownAndWait(seconds : number)
	NEXT_ATTACK_TIME += seconds
	task.wait(seconds)
end

local function attack()
	local connection = Head.Touched:Connect(function(hit)
		if NEXT_ATTACK_TIME > tick() then return end -- don't allow attacks before the cooldown has run out
		
		
		if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 then
			NEXT_ATTACK_TIME = tick() + COOLDOWN
			
			hit.Parent.Humanoid:TakeDamage(10)
			Entity.Humanoid.WalkSpeed = Stopping

			Attack:Play()
			increaseCooldownAndWait(1)
			Attack:Stop()

			Entity.Humanoid.WalkSpeed = Walkspeed
		end
	end)
end

Best regards,
Pinker

2 Likes

Ah ok I think I see what you are saying now! So if I want to make it attack while next to the player I should intergrate the attack function into the AIs pathfinding function?

Also that is a nice code, especially how you replaced Debounce. Thank you for showing me this!

2 Likes

You’re better off with magnitude checks than raycasts or .Touched(). Touched is just plain inconsistent, and raycasts require movement to do anything.

3 Likes

More or less, yes. You could check how far the player is away, and if he’s in the attack radius you get all parts and see if one is part of the player.

Of course this varies depending on how you want to implement this. There’s no real right way.
You could also just check how far the player is away and not even check for parts in the radius.


PS: Thanks for the compliment. :+1:


Best regards,
Pinker

2 Likes

Thank you so much for the advice!!

With your help I have figured that just using a radious system in Pathfinding then a Touched:Connect service, it allows the AI to attck while the player is not moving.

Also do you mind if I use your NEXT_ATTCK_TIME method in my code?
It is a lot more clean cut than the one I had originally. I can credit you in the code and stuff.

1 Like

No, I’d love to see this kind of method used more often instead of debounce.


Best regards and good luck,
Pinker

2 Likes

Thank you you are the best!!

I will make sure to credit you in the line of code though as it is a really clean way of making a cooldown :smiley:

2 Likes