Attack is spamable despite conditions

I’ve tried and tried, But it seems that if I simply use an autoclicker, the attack can be spammed without limits.

Can somebody tell me why this is?

local character = script.Parent.Parent
local hum:Humanoid = character:WaitForChild('Humanoid')
local animator = hum:FindFirstChildOfClass('Animator')

local CLASS = hum:GetAttribute('CLASS')

local Attack = game.ReplicatedStorage.Remotes.Attack
local AttributeManager = require(game.ReplicatedStorage.Utility.AttributeManager)

local UIS = game:GetService('UserInputService')

local combo = 1

local function setCombo()
	if combo >= 5 then combo = 1 end
	combo = combo + 1
	lastM1 = tick()
end

local function resetCombo()
	task.delay(2, function()
		if tick() - lastM1 >= 1 then
			print('comboreset')
			combo = 1
		end
	end)
end

UIS.InputBegan:Connect(function(key, typing)

	if key.KeyCode == Enum.KeyCode.E or key.UserInputType == Enum.UserInputType.MouseButton1 then

		local attacking = hum:GetAttribute('Attacking')
		local stunned = hum:GetAttribute('Stunned')

		if typing or attacking or stunned then return end
		AttributeManager.ReplicateStateToServer(hum, 'Attacking', true)

		local attackAnim = animator:LoadAnimation(game.ReplicatedStorage.Classes[CLASS].PlayerAnimations.Combat['Attack'..combo])
		attackAnim:Play(1, 10, 2)	

		local hitbox = Instance.new('Part')
		hitbox.Name = 'Hitbox'
		hitbox.Massless = true
		hitbox.Anchored = false
		hitbox.CanCollide = false
		hitbox.Size = Vector3.new(3,3,5)
		hitbox.CFrame = hum.RootPart.CFrame + hum.RootPart.CFrame.LookVector * 3
		hitbox.Parent = hum.RootPart
		hitbox.Transparency = 1

		game.Debris:AddItem(hitbox, .45)

		local params = OverlapParams.new()
		params.FilterDescendantsInstances = {hitbox}

		local weld = Instance.new('WeldConstraint')
		weld.Parent = hum.RootPart
		weld.Name = 'Weld'
		weld.Part0 = hum.RootPart
		weld.Part1 = hitbox

		game.Debris:AddItem(weld, .45)

		local params = OverlapParams.new()
		params.FilterDescendantsInstances = {hitbox}

		attackAnim:GetMarkerReachedSignal('Damage'):Connect(function()
			
			AttributeManager.ReplicateStateToServer(hum, 'Attacking', false)
			setCombo()

			local hittable = {}

			while true do
				local parts = workspace:GetPartsInPart(hitbox)
				for _, part in pairs(parts) do
					if part:IsA('BasePart') and part.Parent:FindFirstChildOfClass('Humanoid') and part.Parent ~= character and not table.find(hittable, part.Parent) then
						local victim = part.Parent:FindFirstChildOfClass('Humanoid')
						table.insert(hittable, part.Parent)

						if victim.Health <= 0 then return end

						Attack:FireServer(victim)

						victim = nil
					end
				end
				break
			end
			
		end)
	end
end)
2 Likes

Make sure that your code is getting to this part (add some print statements)

And also make sure to check on the server (while playtesting) to make sure the attribute actually changes

It gets to that twice, afterwards it stops checking it as false.

1 Like

Well, that’s a separate version of the script actually, this one fails to check it as true after about 5 clicks

1 Like

This kinda seems like an issue that you cant fix fully. Maybe implement a rate limit or debounce and see if it’s not working just because of how fast you’re firing the ability

1 Like

Although I dont know how to solve your problem but why is this a client script that redundnt
hackers can kill the whole server and have no cooldowns everything should be done on the server and It will most likely fix your issue

They need to utilize UserInputService in order to actually detect input

And I do agree, exploiters can probably easily exploit this script but they can even take advantage of RemoteEvents.

There’s not really any “100% safe way” to do this

you could use debounce for a player slows down the attack.

1 Like

This is an experimental script, that’s why.

for how to do this just use a remote to fire every click (although this might have a small hitbox delay your welding it anyways) and just be like:

--Services
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--Remotes
local FireRemote = ReplicatedStorage.__RemotePath


--Functionality
UserInputService.InputBegan:Connect(function(Input,GameprocessedEvent)
	if GameprocessedEvent then return end -- dont need checks to stop hackers bc its just for QOL
	if Input.KeyCode == Enum.KeyCode.E or Input.UserInputType == Enum.UserInputType.MouseButton1 then
		FireRemote:FireServer() -- empty since we will use the server replication on the character
	end
end)

Not in a rude or to insult you but are you new to scripting?

No, I’ve been scripting for months.

No im not lol. Been doing Lua and full stack development for a couple of years (3/4 years)

Oh really roblox vm lua or base lua? that cool :slight_smile:

Is my solution going to work for your use case?

Ehhh a bit of both but y’know obviously more Roblox Lua (Luau)

I put it on the server, I redid the whole script, exact same issue. Despite the conditions.

Here’s what I’ve found - It follows the 3 second task.wait(3), though after the wait is over, it will play the animation track as many times as the player clicks, as if it knows to wait but doesn’t know to play only one animation. I will experiment with :

if animation.IsPlaying then
-- Logic
end

I’ve come back to say, this did not work whatsoever.

So you want the animation for each punch to play fully? if so that you can use AnimationTrack.Finished or .Completed forgot which one it was and set the attacking to false their instead