How to make the damage take only once

hello, when i use the script the damage happends multiple times. i would like any help

	local Debris = game:GetService("Debris")
	local humRP = player.Character.HumanoidRootPart
	local TweenS = game:GetService("TweenService")
	local damage = 30
	local filterObjects = {}
	local boxSize = partSize
	local params = OverlapParams.new(filterObjects,Enum.RaycastFilterType.Blacklist,5,"Default")
	local parts = workspace:GetPartBoundsInBox(PartCFr ,boxSize,params) 
	for i,v in pairs(parts) do
		if v.Parent ~= player.Character and v.Parent:FindFirstChild("Humanoid") then
			v.Parent.Humanoid.Health -= damage
			local Speed = 40
			local Force = 80000
			local TotalForce = Force
			local KnockBack = Instance.new("BodyVelocity")
			KnockBack.Parent = v.Parent:FindFirstChild("HumanoidRootPart")
			KnockBack.MaxForce = Vector3.new(TotalForce,TotalForce,TotalForce)
			KnockBack.Velocity = PartCFr.LookVector * Speed 
			Debris:AddItem(KnockBack,.25)
			local damageI = game:GetService("ReplicatedStorage").DmgIndicator:Clone()
			damageI.Parent = v.Parent.HumanoidRootPart
			damageI.TextLabel.Text = "-"..damage
			damageI.StudsOffset = Vector3.new(math.random(-2,2),math.random(-2,2),math.random(-2,2))
			local TweenDmg = TweenS:Create(damageI,TweenInfo.new(1,Enum.EasingStyle.Bounce,Enum.EasingDirection.Out, 0, false), {Size = UDim2.new(2,0,2,0)})
			TweenDmg:Play()
			TweenDmg.Completed:Connect(function()
				local TweenDmg2 = TweenS:Create(damageI,TweenInfo.new(1,Enum.EasingStyle.Bounce,Enum.EasingDirection.Out, 0, false),{Size = UDim2.new(0,0,0,0)})
				TweenDmg2:Play()
			end)
		end
	end
2 Likes

Create a debounce, so it only does it again after a varied amount of time.

but will it hit multipe players then?

If it does now, it will then. If it doesn’t now, it won’t then.

A debounce is a cooldown.

Debounces wouldn’t be the way to do this as I believe this is a server script.

I’d recommend making a table of players who been hit, then clear it afterwards.

i have tried making a table in the past, but i couldnt get it to work

local playersDebounce = {}
function DoThisThing(userId)
    if playersDebounce[userId] == true then return end
    playersDebounce[userId] = true
end

1 Like

You would be able to do this by doing this:

local PlayersHit = {}

(your stuff here)
if PlayersHit[plr] then return end
plr.Humanoid.Health -= 1
table.insert(PlayersHit, plr)

(afterwards)
table.clear(PlayersHit)

(What @hatespine posted should also work, but I just added clearing)

1 Like

table library should be used for arrays instead, nonetheless this is a good example

even though roblox Lua is very fast, please make sure to set the debounce (for most use cases) at the start of the function, so there isn’t the possibility of the function being able to run twice in a very rare case

1 Like

when should i clear the table? should i add a wait?

Whenever you want?.. if you are wishing to do so

I’d recommend you clear the table after the for i,v parts function. And there’s no reason to add a wait as it already yields.

Rather than using tables, you can give boolvalues a try, simply create a boolvalue instead character or replicatedstorage with their player.name as the boolvalue name then make it true if they get hit.
It would work sorta like this

if ReplicatedStorage:WaitForChild(Player.Name).Value == true then return end -- dont damage them
1 Like

why would they need to use a boolvalue instead of a table? and why using the player username instead of the userid

you’d also need to have a boolvalue for each player

It’s simpler.

Either way could work.

it still does damage multiple times and it does only damage to the player and the players that get hit, and not npcs.

It’s not simpler, you can define a table just by doing this:
local tab = {}

while your method needs to create boolvalues and remove them upon playeradded playerremoving

local debounces = {
     ["Players"] = {},
     ["Others"] = {},
}
function DoThisThing(isPlayer, userId)
    if (isPlayer == true and debounces["Players"][userId] == true) or (debounces["Others"][userId] == true) then return end
    if isPlayer == true then
      debounce["Players"][userId] = true
    else
      debounce["Others"][userId] = true
    end
end

--In the case of an NPC just call DoThisThing with the NPC's name
--If you want you can remove the debounces upon player getting removed or after some time, you will need to code that

The reason there’s two different tables for NPCs and Players is because well, its better not to mix them:

There could be a rare case in which you named an NPC the same as somebody’s userId, and then used tonumber() on it which would make that NPC and that other player have the same debounce lol

Also please know what you are coding or the code you are working with instead of blaming your errors on us, our code should fix what your Topic said

but when calling the funtion what is going in the isPlayer varible

local players = game:GetService("Players")



local player = players:GetPlayerByUserId(userIdHere) --You could also use :GetPlayerFromCharacter()
if player then --It means it is a player
   DoThisThing(true, player.UserId)
else
   DoThisThing(false, theNpcName)
end