Hello, I am scripting a combat system similar to that of the “battleground” genre. This is the script for the basic punch (or M1) combo, where the player punches another player four times and knocks them back on the final punch. You can do the combo automatically by holding down the M1 button, however, sometimes randomly the M1 combo will stop. I’ve tried to locate exactly where or when this happens, but I can’t figure it out. I’ve put print functions after every return, and the code seems to be running all the way through. Please can somebody give me some pointers?
-- Modules
local replicatedStorage = game:GetService("ReplicatedStorage")
local modules = replicatedStorage.Modules
local hitbox = require(modules.BumperHitboxes)
local stun = require(modules.StunHandlerV2)
local attackStun = require(modules.AttackStunHandlerV2)
-- Variables
local tool = script
local anims = replicatedStorage.Animations
local cd = false
local equipped = false
local character = script.Parent
local player = game.Players:GetPlayerFromCharacter(character)
local human = character.Humanoid
local comboResetTimer
local lastComboNum
local equippedAnim
local vfx = replicatedStorage.VFX
local anim1
local anim2
local anim3
local anim4
local mouseHeld = false
-- Config
local swingAnims = {anims.Attack1, anims.Attack2, anims.Attack3, anims.Attack4}
local m1HitAnims = {anims.Hit1, anims.Hit2, anims.Hit3, anims.Hit4}
local equipAnims = {anims.Idle}
anim1 = human.Animator:LoadAnimation(swingAnims[1])
anim2 = human.Animator:LoadAnimation(swingAnims[2])
anim3 = human.Animator:LoadAnimation(swingAnims[3])
anim4 = human.Animator:LoadAnimation(swingAnims[4])
-- SFX Putting
for i, sound in pairs(script.SFX:GetChildren()) do
sound.Parent = character.HumanoidRootPart
end
local hitSound = character.HumanoidRootPart.Punch
local hitSoundFlourish = character.HumanoidRootPart.Flourish
local swingSound = character.HumanoidRootPart.Swing
-- M1 Function
local function M1(plr, mouseDown)
if mouseDown == true then
mouseHeld = true
else
mouseHeld = false
return
end
if plr ~= player then return end
if cd == true then
wait(0.1)
if mouseHeld == true then
M1(plr, true)
return
end
return
end
if character:GetAttribute("Stunned") == true then
wait(0.1)
if mouseHeld == true then
M1(plr, true)
return
end
return
end
if character:GetAttribute("AttackStun") == true then
wait(0.1)
if mouseHeld == true then
M1(plr, true)
return
end
return
end
if character:GetAttribute("DashAttacking") == true then
if mouseHeld == true then
repeat
wait()
until character:GetAttribute("DashAttacking") == false
wait(0.1)
M1(plr, true)
return
end
return
end
if character:GetAttribute("AttackStunAlt") == true then
if mouseHeld == true then
wait(0.1)
M1(plr, true)
return
end
return
end
cd = true
character:SetAttribute("AttackStunAlt", true)
-- Animations & Combo
local currentComboNum = tool:GetAttribute("ComboNum")
task.spawn(function()
if currentComboNum == 1 then
tool:SetAttribute("ComboNum", currentComboNum + 1)
anim1:AdjustWeight(0.0001, 0.0001)
anim1:Play()
local trail = Instance.new("Trail")
trail.Transparency = NumberSequence.new(0.5, 1)
trail.Lifetime = 0.25
trail.FaceCamera = true
local attachment1 = Instance.new("Attachment")
attachment1.Parent = character["Right Arm"]
attachment1.WorldPosition = character["Right Arm"].Position
trail.Parent = character["Right Arm"]
trail.Attachment0 = character["Right Arm"].RightGripAttachment
trail.Attachment1 = attachment1
task.spawn(function()
task.wait(0.3)
character:SetAttribute("AttackStunAlt", false)
attachment1:Destroy()
end)
elseif currentComboNum == 2 then
tool:SetAttribute("ComboNum", currentComboNum + 1)
anim2:AdjustWeight(10, 0.0001)
anim2:Play()
anim1:Stop()
local trail = Instance.new("Trail")
trail.Transparency = NumberSequence.new(0.5, 1)
trail.Lifetime = 0.25
trail.FaceCamera = true
local attachment1 = Instance.new("Attachment")
attachment1.Parent = character["Left Arm"]
attachment1.WorldPosition = character["Left Arm"].Position
trail.Parent = character["Left Arm"]
trail.Attachment0 = character["Left Arm"].LeftGripAttachment
trail.Attachment1 = attachment1
task.spawn(function()
task.wait(0.3)
character:SetAttribute("AttackStunAlt", false)
attachment1:Destroy()
end)
elseif currentComboNum == 3 then
tool:SetAttribute("ComboNum", currentComboNum + 1)
anim3:AdjustWeight(30, 0.0001)
anim3:Play()
anim2:Stop()
local trail = Instance.new("Trail")
trail.Transparency = NumberSequence.new(0.5, 1)
trail.Lifetime = 0.25
trail.FaceCamera = true
local attachment1 = Instance.new("Attachment")
attachment1.Parent = character["Right Arm"]
attachment1.WorldPosition = character["Right Arm"].Position
trail.Parent = character["Right Arm"]
trail.Attachment0 = character["Right Arm"].RightGripAttachment
trail.Attachment1 = attachment1
task.spawn(function()
task.wait(0.3)
character:SetAttribute("AttackStunAlt", false)
attachment1:Destroy()
end)
else
task.spawn(function()
task.wait(0.4)
attackStun.Stun(human, 0.5)
end)
tool:SetAttribute("ComboNum", 1)
anim4:AdjustWeight(40, 0.0001)
anim4:Play()
anim3:Stop()
local trail = Instance.new("Trail")
trail.Transparency = NumberSequence.new(0.5, 1)
trail.Lifetime = 0.25
trail.FaceCamera = true
local attachment1 = Instance.new("Attachment")
attachment1.Parent = character["Left Arm"]
attachment1.WorldPosition = character["Left Arm"].Position
trail.Parent = character["Left Arm"]
trail.Attachment0 = character["Left Arm"].LeftGripAttachment
trail.Attachment1 = attachment1
task.spawn(function()
task.wait(0.3)
character:SetAttribute("AttackStunAlt", false)
attachment1:Destroy()
end)
end
end)
local currentComboNum = tool:GetAttribute("ComboNum")
lastComboNum = tool:GetAttribute("ComboNum")
-- Hitbox & Damage
task.spawn(function()
local HitTable = {}
wait(0.05)
swingSound:Play()
wait(0.1)
local hitParts = hitbox:Create(player, Vector3.new(6,6,6), character.HumanoidRootPart.CFrame.LookVector * 3)
for i, part in pairs(hitParts) do
if not part:HasTag("VFX") and part.Name ~= "Hitbox" then
if part.Parent:FindFirstChild("Humanoid") then
if not table.find(HitTable, part.Parent) then
if part.Parent ~= character then
if character:GetAttribute("Stunned") == true then return end
if part.Parent:GetAttribute("Ragdolled") == true then return end
if part.Parent:GetAttribute("Blocking") == true then
local ObjectSpace = part.Parent.HumanoidRootPart.CFrame:inverse() * character.HumanoidRootPart.CFrame
local MaxDistance = 100
if ObjectSpace.Z < 0 and (character.HumanoidRootPart.CFrame.p - part.Parent.HumanoidRootPart.CFrame.p).magnitude <= MaxDistance then
part.Parent.Humanoid.Animator:LoadAnimation(anims.Blockhit):Play()
character.HumanoidRootPart.BlockHit:Play()
return
end
end
table.insert(HitTable, part.Parent)
part.Parent:SetAttribute("Blocking", false)
part.Parent.Humanoid:TakeDamage(tool:GetAttribute("Damage"))
local animations = part.Parent.Humanoid.Animator:GetPlayingAnimationTracks()
for i, anim in pairs(animations) do
if anim == "Block" then
anim:Stop()
end
end
if currentComboNum == 1 then
hitSoundFlourish:Play()
stun.Stun(part.Parent.Humanoid, 1.2)
local slide = Instance.new("BodyVelocity")
slide.MaxForce = Vector3.new(1,1,1) * 30000
slide.Velocity = character.HumanoidRootPart.CFrame.lookVector * 45 + Vector3.new(0, 0, 0)
slide.Parent = part.Parent.HumanoidRootPart
task.spawn(function()
wait(0.2)
slide:Destroy()
end)
task.spawn(function()
part.Parent.Ragdoll.Value = true
task.wait(1.2)
part.Parent.Ragdoll.Value = false
end)
-- VFX
task.spawn(function()
local trail = Instance.new("Trail")
trail.Transparency = NumberSequence.new(0.5, 1)
trail.Lifetime = 0.25
trail.FaceCamera = true
local trail2 = Instance.new("Trail")
trail2.Transparency = NumberSequence.new(0.5, 1)
trail2.Lifetime = 0.25
trail2.FaceCamera = true
local trail3 = Instance.new("Trail")
trail3.Transparency = NumberSequence.new(0.5, 1)
trail3.Lifetime = 0.25
trail3.FaceCamera = true
local trail4 = Instance.new("Trail")
trail4.Transparency = NumberSequence.new(0.5, 1)
trail4.Lifetime = 0.25
trail4.FaceCamera = true
local attachment1 = Instance.new("Attachment")
local attachment2 = Instance.new("Attachment")
local attachment3 = Instance.new("Attachment")
local attachment4 = Instance.new("Attachment")
attachment1.Parent = part.Parent["Left Arm"]
attachment1.WorldPosition = part.Parent["Left Arm"].Position
trail.Parent = part.Parent["Left Arm"]
trail.Attachment0 = part.Parent["Left Arm"].LeftGripAttachment
trail.Attachment1 = attachment1
attachment2.Parent = part.Parent["Right Arm"]
attachment2.WorldPosition = part.Parent["Right Arm"].Position
trail2.Parent = part.Parent["Right Arm"]
trail2.Attachment0 = part.Parent["Right Arm"].RightGripAttachment
trail2.Attachment1 = attachment2
attachment3.Parent = part.Parent["Right Leg"]
attachment3.WorldPosition = part.Parent["Right Leg"].Position
trail3.Parent = part.Parent["Right Leg"]
trail3.Attachment0 = part.Parent["Right Leg"].RightFootAttachment
trail3.Attachment1 = attachment3
attachment4.Parent = part.Parent["Left Leg"]
attachment4.WorldPosition = part.Parent["Left Leg"].Position
trail4.Parent = part.Parent["Left Leg"]
trail4.Attachment0 = part.Parent["Left Leg"].LeftFootAttachment
trail4.Attachment1 = attachment4
wait(1.2)
trail.Enabled = false
trail2.Enabled = false
trail3.Enabled = false
trail4.Enabled = false
wait(1)
attachment1:Destroy()
trail:Destroy()
attachment2:Destroy()
trail2:Destroy()
attachment3:Destroy()
trail3:Destroy()
attachment4:Destroy()
trail4:Destroy()
end)
-- Knockback on flourish
elseif currentComboNum == 2 then
hitSound:Play()
local anim = part.Parent.Humanoid.Animator:LoadAnimation(anims.Hit1)
anim:Play()
stun.Stun(part.Parent.Humanoid, 0.7)
elseif currentComboNum == 3 then
hitSound:Play()
local anim = part.Parent.Humanoid.Animator:LoadAnimation(anims.Hit2)
anim:Play()
stun.Stun(part.Parent.Humanoid, 0.7)
else
hitSound:Play()
local anim = part.Parent.Humanoid.Animator:LoadAnimation(anims.Hit3)
anim:Play()
stun.Stun(part.Parent.Humanoid, 0.7)
end
-- VFX
local punchParticle = vfx.PunchParticle:Clone()
punchParticle.Parent = part.Parent.Torso
punchParticle:Emit(1)
task.spawn(function()
wait(0.3)
punchParticle:Destroy()
end)
end
end
end
end
end
HitTable = {}
end)
-- Cooldowns
if currentComboNum == 1 then
wait(tool:GetAttribute("ComboCooldown"))
else
wait(tool:GetAttribute("M1Cooldown"))
end
cd = false
wait(0.1)
if mouseHeld == true then
M1(plr, true)
return
end
-- Combo Reset
wait(2.5)
if currentComboNum == lastComboNum then
tool:SetAttribute("ComboNum", 1)
end
end
replicatedStorage.Events.M1.OnServerEvent:Connect(M1)