Hello everyone! I’ve run into yet another problem with this combat script that I need to go back to you all for.
I’ll let this video speak for itself.
You can see what happens here is I swing 5 times then hit the NPC once, and it seems to stack up the hits even when I miss them before actually landing a hit on anything. This makes no sense to me, because in the Attack() function which controls dealing damage and stunning the enemy, damage will only be dealt if the hitbox detects something inside of it, as well as blacklisting that enemy from being hit multiple times in the same swing.
What really puzzles me is that this only happened after I implemented the “Combo Reset” system. It could’ve been something to do with me tidying up my code and accidentally creating a logic error when I did, but I went and ported the new features I have in the script now back to my old iteration, and the same issues persisted.
Anyway, here’s the code.
-- // Variables
local tool = script.Parent
local anims = script.Parent.Animations
local ws = game:GetService("Workspace")
local box = tool.box
local box2 = tool.box2
local oparams = OverlapParams.new()
oparams.FilterType = Enum.RaycastFilterType.Exclude
oparams.MaxParts = math.huge
local effect = script.Parent.Handle.Blood
local btrail = script.Parent.Handle.BloodTrail
-- // Controls
local equip
local slash
local idle
local db = false
local canHit = false
local hitboxed = false
local randomSlash = 1
local boxc
local value
local slashval = tool.Slash
local dewit = true
local resetthread = nil
local didHit = false -- messy variable
-- // Animation Startup
script.Parent.Equipped:Connect(function()
tool.Handle.Equip:Play()
local humanoid = script.Parent.Parent:FindFirstChild("Humanoid")
if not equip then equip = humanoid:LoadAnimation(anims.Equip) end
equip:Play()
if not idle then idle = humanoid:LoadAnimation(anims.Idle) end
idle.Priority = Enum.AnimationPriority.Movement
idle:Play()
end)
-- // Animation Shutdown
script.Parent.Unequipped:Connect(function()
if idle then idle:Stop() end
if equip then equip:Stop()
if slash then slash:Stop() end
end
end)
-- // Light Attack Reset CD
local animCD = function()
print("combo cd has begun")
task.wait(2)
randomSlash = 1
slashval.Value = randomSlash
print("combo has been reset")
end
--// Prevent Combo Reset
slashval.Changed:Connect(function()
if resetthread == nil then print("combo reset perceived nil") return end
coroutine.yield(resetthread)
coroutine.close(resetthread)
print("combo reset cancelled")
end)
-- // Light Attacks
script.Parent.Activated:Connect(function()
local char = tool.Parent
local root = char:WaitForChild("HumanoidRootPart")
local hum = char:WaitForChild("Humanoid")
if char.Stunned.Value or char.Dashing.Value or db then return end
db = true
local function Attack()
if canHit or not db or hitboxed then return end
canHit = true
hitboxed = true
local doKnockback = false
if randomSlash == 1 or randomSlash == 2 or randomSlash == 5 then
boxc = box:Clone()
value = -3
elseif randomSlash == 3 or randomSlash == 4 then
boxc = box2:Clone()
value = -5
end
if didHit == false then didHit = true end
oparams.FilterDescendantsInstances = {char}
local humanoidsDamaged = {}
tool.ClickEvent.OnServerEvent:Connect(function(plr, cf)
boxc.Parent = ws.Scripted
boxc.CFrame = cf * CFrame.new(0,0,value)
game:GetService("Debris"):AddItem(boxc,0.3)
local hits = ws:GetPartsInPart(boxc,oparams)
for i = 1, #hits do
if hits[i].Parent ~= char and hits[i].Parent:FindFirstChild("Humanoid") and hits[i].Parent:FindFirstChild("Dashing") and char.Stunned.Value == false then
if hits[i].Parent.Dashing.Value == false and not table.find(humanoidsDamaged, hits[i].Parent.Parent) then
table.insert(humanoidsDamaged, hits[i].Parent.Parent)
local hitSFX = Instance.new("Sound",hits[i].Parent.Head)
hitSFX.SoundId = "rbxassetid://566593606"; hitSFX:Play()
hits[i].Parent.Humanoid:TakeDamage(5)
hits[i].Parent:FindFirstChild("Hitstun"):Fire()
if randomSlash == 1 and didHit == true then
local delta = hits[i].Parent:FindFirstChild("HumanoidRootPart").Position - root.Position
local bv = Instance.new("BodyVelocity")
bv.maxForce = Vector3.new(1e9, 1e9, 1e9)
bv.velocity = delta.unit * 128
bv.Parent = hits[i].Parent:FindFirstChild("HumanoidRootPart")
game:GetService("Debris"):AddItem(bv, 0.01)
end
effect.Enabled = true
btrail.Enabled = true
local slashfx = tool.Effects.Slash.Attachment:Clone()
slashfx.Parent = hits[i].Parent:FindFirstChild("HumanoidRootPart")
local r = math.random(-360,360)
slashfx.slash.Rotation = NumberRange.new(r)
task.delay(0.3,function()
slashfx:Destroy()
end)
end
task.delay(0.2,function()
effect.Enabled = false
btrail.Enabled = false
end)
end
end
end)
task.delay(0.3,function()
canHit = false
hitboxed = false
end)
end
Attack()
if not slash then
slash = hum:LoadAnimation(anims["Attack".. randomSlash])
if randomSlash == 5 then
randomSlash = 1
slashval.Value = randomSlash
print("randomslash set to "..randomSlash)
else
randomSlash += 1
slashval.Value = randomSlash
print("randomslash set to "..randomSlash)
end
end
local val = tool.Parent.Attacking
val.Value = true
slash:Play()
script.Parent.Handle.Trail.Enabled = true
task.wait(.15)
tool.Handle.Slash:Play()
if randomSlash == 5 or randomSlash == 4 then
tool.Handle.Chain:Play()
end
task.wait(.15)
hitboxed = false
if slash then
slash = nil
end
script.Parent.Handle.Trail.Enabled = false
resetthread = coroutine.create(animCD)
coroutine.resume(resetthread)
print("combo reset coroutine created")
if randomSlash == 1 then
task.wait(2)
db = false
else
db = false
end
task.delay(.15,function()
val.Value = false
end)
end)
Any help is appreciated, thank you.
P.S: Any clarification you need as to what certain variables or things are, just let me know and I’ll explain.