BaseMechanics.InflictDamage = function(Hitbox:Part, Attacker:Model, Damage, Knockback, PostureDamage, Blockable, Dodgeable, Parryable, StatusEffects)
local AlreadyHit = {}
Hitbox.Touched:Connect(function()
local PartsHitByAttack = workspace:GetPartsInPart(Hitbox)
for i, Part:Part in pairs(PartsHitByAttack) do
local TargetCharacter = Part.Parent
if not table.find(AlreadyHit, TargetCharacter) and TargetCharacter ~= nil and TargetCharacter:FindFirstChildOfClass("Humanoid") and TargetCharacter ~= Attacker then
print("does this part loop?")
local TargetHumanoid:Humanoid = TargetCharacter:FindFirstChildOfClass("Humanoid")
table.insert(AlreadyHit, TargetCharacter)
local AlreadyHitClearer = coroutine.wrap(function()
task.wait(3)
table.remove(AlreadyHit, table.find(AlreadyHit, TargetCharacter))
print("Cleared")
end)
AlreadyHitClearer()
local ApplyStatusEffects = function()
for i, Effect in pairs(StatusEffects) do
local x = 0
print(i, Effect, x + 1)
Effect(TargetCharacter, Damage)
end
end
print("is this looping")
if Knockback ~= nil or Knockback > 0 then
TargetHumanoid:ChangeState(Enum.HumanoidStateType.Ragdoll, true)
local KnockbackVelocity = Instance.new("LinearVelocity")
KnockbackVelocity.Enabled = true
KnockbackVelocity.MaxForce = 10000000
KnockbackVelocity.Attachment0 = TargetCharacter:FindFirstChild("HumanoidRootPart"):FindFirstChild("RootAttachment")
KnockbackVelocity.VectorVelocity = Attacker.PrimaryPart.CFrame.LookVector * Knockback
KnockbackVelocity.Parent = TargetCharacter.PrimaryPart
DebrisService:AddItem(KnockbackVelocity, .3)
end
if Blockable == true or Blockable ~= true then
if Blockable == true then
if TargetHumanoid:GetAttribute("IsBlocking") == true then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture + PostureDamage)
if TargetHumanoid:GetAttribute("Posture") >= TargetHumanoid:GetAttribute("MaxPosture") then
PostureBroken(TargetHumanoid)
TargetHumanoid:TakeDamage(Damage)
--ApplyStatusEffects()
end
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
end
elseif Dodgeable == true or Dodgeable ~= true then
if Dodgeable == true then
if TargetHumanoid:GetAttribute("IsDodging") == true then
print("Attack Dodged")
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
--ApplyStatusEffects()
end
end
elseif Parryable == true or Parryable ~= true then
if Parryable == true then
if TargetHumanoid:GetAttribute("IsParrying") == true then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture - 10)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
--ApplyStatusEffects()
end
end
elseif TargetHumanoid:GetAttribute("Evasions") > 0 or TargetHumanoid:GetAttribute("Evasions") == 0 then
if TargetHumanoid:GetAttribute("Evasions") > 0 then
TargetHumanoid:SetAttribute("Evasions", TargetHumanoid:GetAttribute("Evasions") - 1)
HitStun(TargetHumanoid)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
--ApplyStatusEffects()
end
end
end
end
end)
end
My code used to be fine before I added the ApplyStatusEffects() Function. Whenever I would run it without that function, :TakeDamage and HitStun(TargetHumanoid) Would run ONLY once as intended. However the moment I uncomment the ApplyStatusEffects(), if my AlreadyHitClearer ends before the Status Effect that is applied ends, it reactivates TargetHumanoid:TakeDamage(Damage), HitStun(TargetHumanoid), AND ApplyStatusEffects().
Why does ApplyStatusEffects() in particular cause all of these problems? Why is it fine when that function is gone?
local ApplyStatusEffects = function()
for i, Effect in pairs(StatusEffects) do
local x = 0
print(i, Effect, x + 1)
Effect(TargetCharacter, Damage)
end
end
But if you’re looking for the actual function itself:
StatusEffectFunction = function(Character:Model, AttackDamage)
local Humanoid = Character:FindFirstChildOfClass("Humanoid")
local DamageToDeal = ElementsModule.FireMagic.Damage * AttackDamage
if Humanoid:GetAttribute("Burning") == nil then
Humanoid:SetAttribute("Burning", ElementsModule.FireMagic.StatusEffectLength)
while Humanoid:GetAttribute("Burning") ~= nil and Humanoid:GetAttribute("Burning") > 0 do
task.wait(1)
Humanoid:SetAttribute("Burning", Humanoid:GetAttribute("Burning") - 1)
Humanoid:SetAttribute("Temperature", Humanoid:GetAttribute("Temperature") + 1)
Humanoid:TakeDamage(AttackDamage)
if Humanoid:GetAttribute("Burning") == 0 then
Humanoid:SetAttribute("Burning", nil)
end
end
elseif Humanoid:GetAttribute("Burning") ~= nil then
Humanoid:SetAttribute("Burning", ElementsModule.FireMagic.StatusEffectLength)
end
end,
I think that without ApplyStaticEffects the code runs fast enough that all the parts are marked hit before Touched fires again. With ApplyStaticEffects the function delays enough that some parts aren’t being marked hit before the next Touched event fires.
I think you could run the PartsHitByAttack loop twice. First, check whether each character was already hit or remember the Humanoid for further processing. The check will then run quickly and not be affected by how long the effects code takes.
local AlreadyHit = {}
Hitbox.Touched:Connect(function()
local HumanoidsHit = {}
local PartsHitByAttack = workspace:GetPartsInPart(Hitbox)
for i, Part:Part in pairs(PartsHitByAttack) do
local TargetCharacter = Part.Parent
if not table.find(AlreadyHit, TargetCharacter) and TargetCharacter ~= nil and TargetCharacter:FindFirstChildOfClass("Humanoid") and TargetCharacter ~= Attacker then
print("does this part loop?")
local TargetHumanoid:Humanoid = TargetCharacter:FindFirstChildOfClass("Humanoid")
table.insert(AlreadyHit, TargetCharacter)
local AlreadyHitClearer = coroutine.wrap(function()
task.wait(3)
table.remove(AlreadyHit, table.find(AlreadyHit, TargetCharacter))
print("Cleared")
end)
AlreadyHitClearer()
table.insert(HumanoidsHit,TargetHumanoid)
end
end
for i, TargetHumanoid in pairs(HumanoidsHit) do
-- Status Effects Code
end
end
local debounce = false
Hitbox.Touched:Connect(function(hit)
if debounce then return end
if hit.Parent:FindFirstChild("Humanoid") then
debounce = true
--
-- Your code
--
end
task.wait(1)
debounce = false
end)
It’s hitting your foot, leg, exc … 16 times. Time for a debounce.
There is a debounce it is under the table AlreadyHit, which is a local table in the function which is why it is being called 16 times. It needs to be a declared at the top of the script. Other than that AlreadyHit is just constantly a blank table.
BaseMechanics.InflictDamage = function(Hitbox:Part, Attacker:Model, Damage, Knockback, PostureDamage, Blockable, Dodgeable, Parryable, StatusEffects)
local AlreadyHit = {}
Hitbox.Touched:Connect(function()
local PartsHitByAttack = workspace:GetPartsInPart(Hitbox)
for i, Part:Part in pairs(PartsHitByAttack) do
local TargetCharacter = Part.Parent
if not table.find(AlreadyHit, TargetCharacter) and TargetCharacter ~= nil and TargetCharacter:FindFirstChildOfClass("Humanoid") and TargetCharacter ~= Attacker then
local TargetHumanoid:Humanoid = TargetCharacter:FindFirstChildOfClass("Humanoid")
table.insert(AlreadyHit, TargetCharacter)
local AlreadyHitClearer = coroutine.wrap(function()
task.wait(3)
table.remove(AlreadyHit, table.find(AlreadyHit, TargetCharacter))
end)
AlreadyHitClearer()
local ApplyStatusEffects = function()
for i, Effect in pairs(StatusEffects) do
Effect(TargetCharacter, Damage)
end
end
if Knockback ~= nil or Knockback > 0 then
TargetHumanoid:ChangeState(Enum.HumanoidStateType.Ragdoll, true)
local KnockbackVelocity = Instance.new("LinearVelocity")
KnockbackVelocity.Enabled = true
KnockbackVelocity.MaxForce = 10000000
KnockbackVelocity.Attachment0 = TargetCharacter:FindFirstChild("HumanoidRootPart"):FindFirstChild("RootAttachment")
KnockbackVelocity.VectorVelocity = Attacker.PrimaryPart.CFrame.LookVector * Knockback
KnockbackVelocity.Parent = TargetCharacter.PrimaryPart
DebrisService:AddItem(KnockbackVelocity, .3)
end
if Blockable then
if TargetHumanoid:GetAttribute("IsBlocking") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture + PostureDamage)
if TargetHumanoid:GetAttribute("Posture") >= TargetHumanoid:GetAttribute("MaxPosture") then
PostureBroken(TargetHumanoid)
TargetHumanoid:TakeDamage(Damage)
ApplyStatusEffects()
end
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Dodgeable then
if TargetHumanoid:GetAttribute("IsDodging") then
print("Attack Dodged")
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Parryable then
if TargetHumanoid:GetAttribute("IsParrying") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture - 10)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif TargetHumanoid:GetAttribute("Evasions") > 0 or TargetHumanoid:GetAttribute("Evasions") == 0 then
if TargetHumanoid:GetAttribute("Evasions") > 0 then
TargetHumanoid:SetAttribute("Evasions", TargetHumanoid:GetAttribute("Evasions") - 1)
HitStun(TargetHumanoid)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
end
end
end
end)
end
local AlreadyHit = {}
BaseMechanics.InflictDamage = function(Hitbox:Part, Attacker:Model, Damage, Knockback, PostureDamage, Blockable, Dodgeable, Parryable, StatusEffects)
Hitbox.Touched:Connect(function()
local PartsHitByAttack = workspace:GetPartsInPart(Hitbox)
for i, Part:Part in pairs(PartsHitByAttack) do
local TargetCharacter = Part.Parent
if not table.find(AlreadyHit, TargetCharacter) and TargetCharacter ~= nil and TargetCharacter:FindFirstChildOfClass("Humanoid") and TargetCharacter ~= Attacker then
local TargetHumanoid:Humanoid = TargetCharacter:FindFirstChildOfClass("Humanoid")
table.insert(AlreadyHit, TargetCharacter)
local AlreadyHitClearer = coroutine.wrap(function()
task.wait(3)
table.remove(AlreadyHit, table.find(AlreadyHit, TargetCharacter))
end)
AlreadyHitClearer()
local ApplyStatusEffects = function()
for i, Effect in pairs(StatusEffects) do
Effect(TargetCharacter, Damage)
end
end
if Knockback ~= nil or Knockback > 0 then
TargetHumanoid:ChangeState(Enum.HumanoidStateType.Ragdoll, true)
local KnockbackVelocity = Instance.new("LinearVelocity")
KnockbackVelocity.Enabled = true
KnockbackVelocity.MaxForce = 10000000
KnockbackVelocity.Attachment0 = TargetCharacter:FindFirstChild("HumanoidRootPart"):FindFirstChild("RootAttachment")
KnockbackVelocity.VectorVelocity = Attacker.PrimaryPart.CFrame.LookVector * Knockback
KnockbackVelocity.Parent = TargetCharacter.PrimaryPart
DebrisService:AddItem(KnockbackVelocity, .3)
end
if Blockable then
if TargetHumanoid:GetAttribute("IsBlocking") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture + PostureDamage)
if TargetHumanoid:GetAttribute("Posture") >= TargetHumanoid:GetAttribute("MaxPosture") then
PostureBroken(TargetHumanoid)
TargetHumanoid:TakeDamage(Damage)
ApplyStatusEffects()
end
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Dodgeable then
if TargetHumanoid:GetAttribute("IsDodging") then
print("Attack Dodged")
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Parryable then
if TargetHumanoid:GetAttribute("IsParrying") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture - 10)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif TargetHumanoid:GetAttribute("Evasions") > 0 or TargetHumanoid:GetAttribute("Evasions") == 0 then
if TargetHumanoid:GetAttribute("Evasions") > 0 then
TargetHumanoid:SetAttribute("Evasions", TargetHumanoid:GetAttribute("Evasions") - 1)
HitStun(TargetHumanoid)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
end
end
end
end)
end```
local AlreadyHit = {}
BaseMechanics.InflictDamage = function(Hitbox:Part, Attacker:Model, Damage, Knockback, PostureDamage, Blockable, Dodgeable, Parryable, StatusEffects)
Hitbox.Touched:Connect(function()
local PartsHitByAttack = workspace:GetPartsInPart(Hitbox)
for _, Part:Part in pairs(PartsHitByAttack) do
local TargetCharacter = Part.Parent
if TargetCharacter and TargetCharacter:FindFirstChildOfClass("Humanoid") and TargetCharacter ~= Attacker and not table.find(AlreadyHit, TargetCharacter) then
local TargetHumanoid = TargetCharacter:FindFirstChildOfClass("Humanoid")
table.insert(AlreadyHit, TargetCharacter)
local ClearHitCooldown = coroutine.wrap(function()
task.wait(3)
table.remove(AlreadyHit, table.find(AlreadyHit, TargetCharacter))
end)
ClearHitCooldown()
local ApplyStatusEffects = function()
for _, Effect in pairs(StatusEffects) do
Effect(TargetCharacter, Damage)
end
end
if Knockback > 0 then
TargetHumanoid:ChangeState(Enum.HumanoidStateType.Ragdoll, true)
local KnockbackVelocity = Instance.new("LinearVelocity")
KnockbackVelocity.Enabled = true
KnockbackVelocity.MaxForce = 10000000
KnockbackVelocity.Attachment0 = TargetCharacter:FindFirstChild("HumanoidRootPart"):FindFirstChild("RootAttachment")
KnockbackVelocity.VectorVelocity = Attacker.PrimaryPart.CFrame.LookVector * Knockback
KnockbackVelocity.Parent = TargetCharacter.PrimaryPart
DebrisService:AddItem(KnockbackVelocity, .3)
end
if Blockable then
if TargetHumanoid:GetAttribute("IsBlocking") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture + PostureDamage)
if TargetHumanoid:GetAttribute("Posture") >= TargetHumanoid:GetAttribute("MaxPosture") then
PostureBroken(TargetHumanoid)
TargetHumanoid:TakeDamage(Damage)
ApplyStatusEffects()
end
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Dodgeable then
if TargetHumanoid:GetAttribute("IsDodging") then
print("Attack Dodged")
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif Parryable then
if TargetHumanoid:GetAttribute("IsParrying") then
local CurrentPosture = TargetHumanoid:GetAttribute("Posture")
TargetHumanoid:SetAttribute("Posture", CurrentPosture - 10)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
elseif TargetHumanoid:GetAttribute("Evasions") > 0 then
TargetHumanoid:SetAttribute("Evasions", TargetHumanoid:GetAttribute("Evasions") - 1)
HitStun(TargetHumanoid)
else
TargetHumanoid:TakeDamage(Damage)
HitStun(TargetHumanoid)
ApplyStatusEffects()
end
end
end
end)
end