What do you want to achieve? Keep it simple and clear!
To fix an attack bug that can exploited in my monster AI
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.
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
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
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
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!
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.
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.