I’ve been working on a sword based game that would let you hit multiple opponents without letting it hit the same person twice
Module Script Parent (If needed)
local rp = game:GetService("ReplicatedStorage")
local basiccombat = rp:WaitForChild("BasicCombat")
local specialcombat = rp:WaitForChild("SpecialCombat")
local sound = script.Parent:WaitForChild("SwordSounds")
local handler = require(script.CombatHandler)
basiccombat.OnServerEvent:Connect(function(Player, sequence)
local character = Player.Character
local h = character.Humanoid
local humrp = character.HumanoidRootPart
local sword = character:FindFirstChild("Sword")
if sword then
local plrAnim, swordAnim, length = handler.getAnimation(h,sword.Controller, sequence)
plrAnim:Play()
swordAnim:Play()
plrAnim:GetMarkerReachedSignal("Hit"):Connect(function()
handler.Attack(Player,character,humrp,length,sequence)
end)
task.delay(length , function()
basiccombat:FireClient(Player)
end)
end
end)
specialcombat.OnServerEvent:Connect(function(Player, sequence)
local character = Player.Character
local h = character.Humanoid
local humrp = character.HumanoidRootPart
local sword = character:FindFirstChild("Sword")
if sword then
local plrAnim, swordAnim, length = handler.getAnimation(h,sword.Controller, sequence)
plrAnim:Play()
swordAnim:Play()
plrAnim:GetMarkerReachedSignal("Hit"):Connect(function()
handler.Attack(Player,character,humrp,length,sequence)
end)
task.delay(length , function()
basiccombat:FireClient(Player)
end)
end
end)
Module Script
local Animations = script:WaitForChild("Animations")
local plr = Animations.plr
local swrd = Animations.Sword
local meshes = script.Meshes
local rp = game:GetService("ReplicatedStorage")
local KeyProvider = game:GetService("KeyframeSequenceProvider")
local debris = game:GetService("Debris")
local VFX = rp:WaitForChild("VFX")
local SSS = game:GetService("ServerScriptService")
local dictonaryHandler = require(SSS:WaitForChild("DictonaryHandler"))
local sounds = SSS:WaitForChild("SwordSounds")
local slashes = sounds:WaitForChild("Slashes")
local handler = {
plrsInCombat = {},
plrStunTime = {},
plrAnims = {
["L"] = plr.R6_Slash3,
["LL"] = plr.R6_Slash2,
["LLL"] = plr.R6_Slash1
},
-- SpinAnims = {
-- ["L"] = plr.R6_Spin
-- },
SwordAnims = {
["L"] = swrd.R6_Sword1,
["LL"] = swrd.R6_Sword2,
["LLL"] = swrd.R6_Sword3
},
SwordHitboxes = {
["L"] = CFrame.Angles(0, 0, math.rad(50)),
["LL"] = CFrame.Angles(0, 0, math.rad(90)),
["LLL"] = CFrame.Angles(0, 0, math.rad(135))
}
}
function handler.getAnimation(Humanoid,SwordAnimationController, sequence)
local length = 0
local keysequence = KeyProvider:GetKeyframeSequenceAsync(handler.plrAnims[sequence].AnimationId)
local keyframes = keysequence:GetKeyframes()
for i=1, #keyframes do
local Time = keyframes[i].Time
if Time > length then
length = Time
end
end
return Humanoid.Animator:LoadAnimation(handler.plrAnims[sequence]), SwordAnimationController.Animator:LoadAnimation(handler.SwordAnims[sequence]), length
end
function handler.Attack(Player,character,humrp,length,sequence)
local folder = Instance.new("Folder")
folder.Name = "SwordCombat"
folder.Parent = workspace
debris:AddItem(folder, .25)
local hitbox = meshes.HitBox:Clone()
hitbox.Size = Vector3.new(2,14,7)
hitbox.Transparency = 0
hitbox.CFrame = humrp.CFrame * CFrame.new(0,.5,-4) * handler.SwordHitboxes[sequence]
hitbox.Parent = folder
local weld1 = Instance.new("ManualWeld")
weld1.Name = "HitboxW"
weld1.Part0 = hitbox
weld1.Part1 = humrp
weld1.C0 = weld1.Part0.CFrame:ToObjectSpace(weld1.Part1.CFrame)
weld1.Parent = weld1.Part0
local connection
connection = hitbox.Touched:Connect(function() end)
local results = hitbox:GetTouchingParts()
if sequence == "LLL" then
humrp.Parent.Humanoid.Jump = true
end
local slash = slashes.OOT_Sword1:Clone()
slash.Parent = workspace
slash:Play()
coroutine.wrap(function()
for _, object in pairs(results) do
if not object:IsDescendantOf(character) then
local Eh = object.Parent:FindFirstChild("Humanoid")
local Ehmrp = object.Parent:FindFirstChild("HumanoidRootPart")
if Eh and Ehmrp and Eh.Health > 0 then
hitbox:Destroy()
if handler.plrsInCombat[character] or dictonaryHandler.find(character, "Stunned") then
return
end
if connection then
connection:Disconnect()
end
if sequence == "LLL" then
Eh:TakeDamage(15)
Eh.Jump = true
else
Eh:TakeDamage(10)
end
local Speed = 40
local Force = 8000
local TotalForce = Force
local KnockBack = Ehmrp:FindFirstChild("BodyVelocity")
if KnockBack.Velocity == 1167 then
return
else
KnockBack.MaxForce = Vector3.new(TotalForce,TotalForce,TotalForce)
KnockBack.Velocity = character:FindFirstChild("HumanoidRootPart").CFrame.LookVector * Speed
wait(.1)
KnockBack.MaxForce = Vector3.new(0,0,0)
end
Eh.Died:Connect(function()
if not Eh:GetAttribute("Dead") then
Eh:SetAttribute("Dead", true)
local leaderstats = Player.leaderstats
print(Player,"Killed",Eh.Parent)
leaderstats.Kills.Value = leaderstats.Kills.Value + 1
end
end)
coroutine.wrap(function()
for _, plr in pairs(game.Players:GetChildren()) do
VFX:FireClient(plr,"SwordVFX","vfx",Ehmrp)
end
end)()
local duration
if string.len(sequence) < 4 then
duration = length * 2
else
duration = length * 3
end
if not handler.plrsInCombat[Eh.Parent] then
handler.plrsInCombat[Eh.Parent] = os.clock()
handler.plrsInCombat[Eh.Parent] = duration
dictonaryHandler.add(Eh.Parent, "Stunned")
Eh.WalkSpeed = 20
slash:Destroy()
else
handler.plrsInCombat[Eh.Parent] = os.clock()
handler.plrStunTime[Eh.Parent] = duration
Eh.WalkSpeed = 20
slash:Destroy()
end
end
end
end
end)()
task.delay(.25, function()
if connection then
connection:Disconnect()
slash:Destroy()
end
end)
end
return handler
This is the module script that handles the sword physics (damage, hitbox size, etc) and I closest solution I’ve found is putting a break after the first end (what I mean is below but, this causes the hitbox to only hit the first person and ignore anyone else. Anyone know an alternative to better suit my situation?
Example
handler.plrsInCombat[Eh.Parent] = os.clock()
handler.plrsInCombat[Eh.Parent] = duration
dictonaryHandler.add(Eh.Parent, "Stunned")
Eh.WalkSpeed = 20
slash:Destroy()
else
handler.plrsInCombat[Eh.Parent] = os.clock()
handler.plrStunTime[Eh.Parent] = duration
Eh.WalkSpeed = 20
slash:Destroy()
end
break -- only one person is hit once.
end
If anything else is needed I’ll gradly provide