Need help with anti auto-clickering my script

So I have a ServerScript for a pet inside of the player’s character that handles movement, damage, and treat/sapphire giving. But when I tested my treat pile with an auto-clicker something sort of expected and another unexpected happened. Firstly, the auto-clicker was able to bypass the attack cooldown, and second, the auto-clicker was able to make the treat give the player treats and sapphires multiple times.

Here is my code for the pet: (ServerScript)

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local EventsFolder = ReplicatedStorage:WaitForChild("Events")
local TreatEvent = EventsFolder:WaitForChild("TreatEvent")

-- Get the player and their humanoid
local player = Players:GetPlayerFromCharacter(script.Parent)
local humanoid = player.Character.Humanoid

local PlayersPets = Instance.new("Folder", game.Workspace)
PlayersPets.Name =  player.Name .. "'s Pets"

-- Create the part to tween
local Pet = game.ReplicatedStorage.Pets.WhitePeacock:Clone()
Pet.Parent =  PlayersPets
local part = Pet:WaitForChild("Base")

local Speed = 0.25
local Action = "Follow"
local PFA = nil -- PFA - 'Part For Action'

TreatEvent.Event:Connect(function(PlayerName, Treat)
	if PlayerName == player.Name then
		local leaderstats = player:FindFirstChild("leaderstats")
		local Treats = leaderstats.Treats
		local Saphires = leaderstats.Saphires
		
		if Treat ~= nil and PFA == nil and Action == "Follow" then
			local Nodes = Treat.Nodes:GetChildren()
			local RandomNode = math.random(1, #Nodes)

			PFA =  Nodes[RandomNode]
			Action = "Attack"
			
			while Treat.Health.Value > 0 do
				if Treat ~= nil and PFA ~= nil and Action ~= "Follow" then
					wait(1)
					if Treat ~= nil and PFA ~= nil and Action ~= "Follow" then
						Treat.Health.Value -= Pet.Damage.Value
					else
						return
					end
					else
					return
				end
			end

			PFA = nil
			Action = "Follow"
			Treats.Value += Treat.Treats.Value
			Saphires.Value += Treat.Saphires.Value
		else
			PFA = nil
			Action = "Follow"
		end
	end
end)

-- Calculate the target position and rotation
RunService.Heartbeat:Connect(function()
	if Action == "Follow" then
		local targetPosition = humanoid.RootPart.Position - (humanoid.RootPart.CFrame.LookVector * 4)
		local targetRotationY = humanoid.RootPart.Rotation.Y -- Extract the Y rotation value
		local targetRotationX = humanoid.RootPart.Rotation.X -- Extract the Y rotation value
		local targetRotationZ = humanoid.RootPart.Rotation.Z -- Extract the Y rotation value

		-- Tween the part to the target position and rotation
		local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
		local tween = TweenService:Create(part, tweenInfo, {
			CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
		})
		
		tween:Play()
		elseif Action == "Attack" then
		for i,  pet in ipairs(PlayersPets:GetChildren()) do
			if PFA ~= nil then
				local targetPosition = PFA.Position
				local targetRotationY = PFA.Rotation.Y -- Extract the Y rotation value
				local targetRotationX = PFA.Rotation.X -- Extract the Y rotation value
				local targetRotationZ = PFA.Rotation.Z -- Extract the Y rotation value

				-- Tween the part to the target position and rotation
				local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
				local tween = TweenService:Create(part, tweenInfo, {
					CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
				})

				tween:Play()
			end
		end
	end
end)

Here are the scripts for the treat pile: (ServerScripts)
-Handles the ClickDetector

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EventsFolder = ReplicatedStorage:WaitForChild("Events")
local TreatEvent = EventsFolder.TreatEvent

script.Parent.ClickDetector.MouseClick:Connect(function(Player)
	TreatEvent:Fire(Player.Name, script.Parent.Parent)
end)

-Handles the piles Respawn

script.Parent.Health.Changed:Connect(function()
	if script.Parent.Health.Value <= 0 then
		task.wait(0.5)
		script.Parent.Parent = game.ReplicatedStorage
		
		task.wait(15)
		
		script.Parent.Health.Value = script.Parent.MaxHealth.Value
		
		task.wait(15)
		
		script.Parent.Parent = game.Workspace.TreetsPiles
	end
end)

These ServerScripts communicate via a BindableEvent so if you don’t recognize the .Event or :Fire functions that’s why.

1 Like

what you need is a debounce

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local EventsFolder = ReplicatedStorage:WaitForChild("Events")
local TreatEvent = EventsFolder:WaitForChild("TreatEvent")

-- Get the player and their humanoid
local player = Players:GetPlayerFromCharacter(script.Parent)
local humanoid = player.Character.Humanoid

local PlayersPets = Instance.new("Folder", game.Workspace)
PlayersPets.Name =  player.Name .. "'s Pets"

-- Create the part to tween
local Pet = game.ReplicatedStorage.Pets.WhitePeacock:Clone()
Pet.Parent =  PlayersPets
local part = Pet:WaitForChild("Base")

local Speed = 0.25
local Action = "Follow"
local PFA = nil -- PFA - 'Part For Action'

local debounce = {}

TreatEvent.Event:Connect(function(PlayerName, Treat)
	if PlayerName == player.Name then
        local found = debounce[PlayerName] -- you could always put one on the client too
          
        if not found or os.clock()-found > 0.1 then
            debounce[PlayerName] = os.clock()
            local leaderstats = player:FindFirstChild("leaderstats")
            local Treats = leaderstats.Treats
            local Saphires = leaderstats.Saphires
            
            if Treat ~= nil and PFA == nil and Action == "Follow" then
                local Nodes = Treat.Nodes:GetChildren()
                local RandomNode = math.random(1, #Nodes)

                PFA =  Nodes[RandomNode]
                Action = "Attack"
                
                while Treat.Health.Value > 0 do
                    if Treat ~= nil and PFA ~= nil and Action ~= "Follow" then
                        wait(1)
                        if Treat ~= nil and PFA ~= nil and Action ~= "Follow" then
                            Treat.Health.Value -= Pet.Damage.Value
                        else
                            return
                        end
                        else
                        return
                    end
                end

                PFA = nil
                Action = "Follow"
                Treats.Value += Treat.Treats.Value
                Saphires.Value += Treat.Saphires.Value
            else
                PFA = nil
                Action = "Follow"
            end
        end
	end
end)

-- Calculate the target position and rotation
RunService.Heartbeat:Connect(function()
	if Action == "Follow" then
		local targetPosition = humanoid.RootPart.Position - (humanoid.RootPart.CFrame.LookVector * 4)
		local targetRotationY = humanoid.RootPart.Rotation.Y -- Extract the Y rotation value
		local targetRotationX = humanoid.RootPart.Rotation.X -- Extract the Y rotation value
		local targetRotationZ = humanoid.RootPart.Rotation.Z -- Extract the Y rotation value

		-- Tween the part to the target position and rotation
		local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
		local tween = TweenService:Create(part, tweenInfo, {
			CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
		})
		
		tween:Play()
		elseif Action == "Attack" then
		for i,  pet in ipairs(PlayersPets:GetChildren()) do
			if PFA ~= nil then
				local targetPosition = PFA.Position
				local targetRotationY = PFA.Rotation.Y -- Extract the Y rotation value
				local targetRotationX = PFA.Rotation.X -- Extract the Y rotation value
				local targetRotationZ = PFA.Rotation.Z -- Extract the Y rotation value

				-- Tween the part to the target position and rotation
				local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
				local tween = TweenService:Create(part, tweenInfo, {
					CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
				})

				tween:Play()
			end
		end
	end
end)

The same problem still arises. Here is a video:


Here is what the piles should be granting:
-----------------Small Pile----------------Large Pile----------
Treats-----|---------25--------------|-----------50-------------|
Spphires–|---------5---------------|------------7--------------|

try this in theory it should fix the issue with bypassing the damage check, I didn’t fix it visually though

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local EventsFolder = ReplicatedStorage:WaitForChild("Events")
local TreatEvent = EventsFolder:WaitForChild("TreatEvent")

-- Get the player and their humanoid
local player = Players:GetPlayerFromCharacter(script.Parent)
local humanoid = player.Character.Humanoid

local PlayersPets = Instance.new("Folder", game.Workspace)
PlayersPets.Name =  player.Name .. "'s Pets"

-- Create the part to tween
local Pet = game.ReplicatedStorage.Pets.WhitePeacock:Clone()
Pet.Parent =  PlayersPets
local part = Pet:WaitForChild("Base")

local Speed = 0.25
local Action = "Follow"
local PFA = nil -- PFA - 'Part For Action'

local lastattacked = {}

local function DebounceCheck(plr)
    local found = lastattacked[plr]

    return not found or found-os.clock() > 1
end

TreatEvent.Event:Connect(function(PlayerName, Treat)
	if PlayerName == player.Name then
        if DebounceCheck(PlayerName) then
            local leaderstats = player:FindFirstChild("leaderstats")
            local Treats = leaderstats.Treats
            local Saphires = leaderstats.Saphires
            
            if Treat and not PFA and Action == "Follow" then
                local Nodes = Treat.Nodes:GetChildren()
                local RandomNode = math.random(1, #Nodes)

                PFA =  Nodes[RandomNode]
                Action = "Attack"
                
                while Treat.Health.Value > 0 do
                    if Treat and PFA and Action ~= "Follow" then
                        if DebounceCheck(PlayerName) then
                            Treat.Health.Value -= Pet.Damage.Value
                            lastattacked[PlayerName] = os.clock()
                        end
                    else
                        break
                    end
                    task.wait()
                end

                PFA = nil
                Action = "Follow"
                Treats.Value += Treat.Treats.Value
                Saphires.Value += Treat.Saphires.Value
            else
                PFA = nil
                Action = "Follow"
            end
        end
	end
end)

-- Calculate the target position and rotation
RunService.Heartbeat:Connect(function()
	if Action == "Follow" then
		local targetPosition = humanoid.RootPart.Position - (humanoid.RootPart.CFrame.LookVector * 4)
		local targetRotationY = humanoid.RootPart.Rotation.Y -- Extract the Y rotation value
		local targetRotationX = humanoid.RootPart.Rotation.X -- Extract the Y rotation value
		local targetRotationZ = humanoid.RootPart.Rotation.Z -- Extract the Y rotation value

		-- Tween the part to the target position and rotation
		local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
		local tween = TweenService:Create(part, tweenInfo, {
			CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
		})
		
		tween:Play()
		elseif Action == "Attack" then
		for i,  pet in ipairs(PlayersPets:GetChildren()) do
			if PFA ~= nil then
				local targetPosition = PFA.Position
				local targetRotationY = PFA.Rotation.Y -- Extract the Y rotation value
				local targetRotationX = PFA.Rotation.X -- Extract the Y rotation value
				local targetRotationZ = PFA.Rotation.Z -- Extract the Y rotation value

				-- Tween the part to the target position and rotation
				local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)
				local tween = TweenService:Create(part, tweenInfo, {
					CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
				})

				tween:Play()
			end
		end
	end
end)

I see what you’re trying to do, but it ends up not attacking after the first time and I have never used clock.os() so I have no idea what the issue could be.

Unrelated but why are you firing a remote event in a LocalScript connected to .MouseClick instead of just making it a server script? You do realize that server scripts can connect to .MouseClick perfectly fine right?

Firstly, it is in a server script;

Secondly, It’s not a RemoteEvent, but instead a BindableEvent which can communicate either:
Server → Server
or
Client → Client

Thanks for clarifying. You can fix this problem by adding a debounce.

Code:

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local EventsFolder = ReplicatedStorage:WaitForChild("Events")
local TreatEvent = EventsFolder:WaitForChild("TreatEvent")

-- Get the player and their humanoid
local player = Players:GetPlayerFromCharacter(script.Parent)
local humanoid = player.Character.Humanoid

local PlayersPets = Instance.new("Folder", game.Workspace)
PlayersPets.Name =  player.Name .. "'s Pets"

-- Create the part to tween
local Pet = game.ReplicatedStorage.Pets.WhitePeacock:Clone()
Pet.Parent =  PlayersPets
local part = Pet:WaitForChild("Base")

local Speed = 0.25
local Action = "Follow"
local PFA = nil -- PFA - 'Part For Action'

local playerDebounces = {}

local tweenInfo = TweenInfo.new(Speed, Enum.EasingStyle.Linear)

TreatEvent.Event:Connect(function(PlayerName, Treat)
	if PlayerName == player.Name then
		local leaderstats = player:FindFirstChild("leaderstats")
		local Treats = leaderstats.Treats
		local Saphires = leaderstats.Saphires

		if Treat and not PFA and Action == "Follow" and not playerDebounces[player] then
			playerDebounces[player] = true
			
			local Nodes = Treat.Nodes:GetChildren()
			local RandomNode = math.random(#Nodes)

			PFA =  Nodes[RandomNode]
			Action = "Attack"

			while Treat.Health.Value > 0 do
				task.wait(1)
				if Treat and PFA and Action ~= "Follow" then
					Treat.Health.Value -= Pet.Damage.Value
				else
					playerDebounces[player] = nil 
					return
				end
			end

			PFA = nil
			Action = "Follow"
			Treats.Value += Treat.Treats.Value
			Saphires.Value += Treat.Saphires.Value
			
			playerDebounces[player] = nil
		else
			PFA = nil
			Action = "Follow"
		end
	end
end)

-- Calculate the target position and rotation
RunService.Heartbeat:Connect(function()
	if Action == "Follow" then
		local targetPosition = humanoid.RootPart.Position - (humanoid.RootPart.CFrame.LookVector * 4)
		local targetRotationY = humanoid.RootPart.Rotation.Y -- Extract the Y rotation value
		local targetRotationX = humanoid.RootPart.Rotation.X -- Extract the Y rotation value
		local targetRotationZ = humanoid.RootPart.Rotation.Z -- Extract the Y rotation value

		-- Tween the part to the target position and rotation
		local tween = TweenService:Create(part, tweenInfo, {
			CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
		})

		tween:Play()
	elseif Action == "Attack" then
		for i, pet in PlayersPets:GetChildren() do
			if PFA then
				local targetPosition = PFA.Position
				local targetRotationY = PFA.Rotation.Y -- Extract the Y rotation value
				local targetRotationX = PFA.Rotation.X -- Extract the Y rotation value
				local targetRotationZ = PFA.Rotation.Z -- Extract the Y rotation value

				-- Tween the part to the target position and rotation
				local tween = TweenService:Create(part, tweenInfo, {
					CFrame = CFrame.new(targetPosition) * CFrame.Angles(math.rad(targetRotationX), math.rad(targetRotationY), math.rad(targetRotationZ))
				})

				tween:Play()
			end
		end
	end
end)
1 Like

Thanks a lot :sweat_smile:, was really bewildering me lol.

By the way, there’s no need for pairs and ipairs now, as Roblox added generalized iteration, which means you can just put the table. It runs faster than pairs and ipairs.

For example, instead of:

for i, part in ipairs(Parts:GetChildren()) do

end

You should do:

for i, part in Parts:GetChildren() do

end

And math.random starts from a default of one, so instead of this:

math.random(1, 10)

You can do:

math.random(10)
1 Like

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