Attacking multiple targets at once?

I am trying to make a sword attack multiple targets at once if they of course get hit by the sword.
My sword consists of a hit-box part that is the touched detection part, when my swing animation gets to a keyframe, the damaging section of the script is active.

script.Parent.Blade.Touched:Connect(function(hit)
	local plr = plrS:FindFirstChild(tool.Parent.Name)
	if hit.Parent or hit.Parent.Parent then
		if hit.Parent:FindFirstChild("Humanoid") then
			if hit.Parent:FindFirstChild("Enemy") or hit.Parent.Parent:FindFirstChild("Enemy") then
				if hit.Parent.Enemy.Value == true then
					local eneH = hit.Parent.Humanoid
					if act then
						if eneH:FindFirstChild("creator") then
							if eneH.creator.Value ~= plr then
								local creator_tag = Instance.new("ObjectValue")
								creator_tag.Value = plr
								creator_tag.Name = "creator"
								creator_tag.Parent = eneH
							end
						else
							local creator_tag = Instance.new("ObjectValue")
							creator_tag.Value = plr
							creator_tag.Name = "creator"
							creator_tag.Parent = eneH
						end
						local dmg = rand:NextNumber(setting.Minimum_Damage,setting.Maximum_Damage)
						module.DamageIndicator(dmg,hit.Parent.Head.CFrame * CFrame.new(rand:NextNumber(-1,1),2,rand:NextNumber(-1,1)))
						eneH:TakeDamage(dmg)
						act = false
					end
				end
			end
		end
	end
end)

^ That is a server script.

‘act’ is the debounce that gets enabled when the animation gets to the keyframe.
Now, It obviously damages only one target, and then the debounce is de-activated.

Where should I start if I want to make it attack multiple targets that the blade hits?
I have tried to create a bool-value in each target that got attacked, and it would’ve been removed after like a second.
But that didn’t seem like the path to go cause it was buggy and weird.

Any suggestions of at least the logic behind making something like that?

Example gif:
https://gyazo.com/52dd778b976459a4e5b389a6773b7c24

I need it to damage both of the targets, that is my goal.

3 Likes

Suggestion


Ideally, I’d use a table that will add up the target hit and spawn a function for it to be removed after X seconds. When attempting to hit the target while the table still has the object indexed, do not run the damage block.

1 Like

I see, this is actually what iv’e started doing right now as you wrote this. Seems like a logical solution.

1 Like

Apologies for my misknowledge about tables, I am very confused and I am not sure what’s wrong here.

							for i = 1, #hitE do
								print(hitE[i])--:GetFullName())
								if hitE[i] ~= eneH then
									table.insert(hitE,i,eneH)
									print(hitE[1]:GetFullName())
									spawn(function()
										wait(.5)
										table.remove(hitE,i)
									end)
								end
							end

hitE is a table I created outside of the Touched function, but it doesn’t print the name, I am not sure whats wrong…

Why would you store the full name of it? Just store the object instead and compare the object whether it is the same character hit.

In other words, insert the character into the table. You don’t need an index to store them.

To insert it into the table, I need the key position, no?
I don’t see where I added the full name of it as well :worried:

I changed it like this, and it seems to work?

							table.insert(hitE,1,eneH)
							for i = 1, #hitE do
								if hitE[i] ~= eneH then
									spawn(function()
										wait(.5)
										table.remove(hitE,i)
									end)
								end
							end

But I don’t know if its right.

-- truncated
local found
for _, character in next, hitE do
    if character ~= eneH then
        -- some boolean toggle for match
        found = true
    end
end

if not found then
    table.insert(hitE, eneH) -- table index at 1 by default, no?
    spawn(function()
        wait(.5)
        for i, character in next, hitE do
            if character == eneH then
                table.remove(hitE, i)
            end
        end
    end)
    -- truncated
end

I just remembered that you still need the index for the removal. Hmm, typical me of overlooking this.

Rewriting the code soon…

1 Like

Rewriting the entire code? Or just that section?

Looks like it is the section. First block checks whether you can find the character in table. The second block adds the character if it’s not found and spawns the function to remove it within X time.

I think it’s also possible to not use spawn at all and place the block of code in the function at the very end of the second block, because the script has an input which is spammable.

Updated

-- truncated
local found
for _, character in next, hitE do
    if character ~= eneH then
        -- some boolean toggle for match
        found = true
    end
end

if not found then
    table.insert(hitE, eneH) -- table index at 1 by default, no?
    
     -- truncated
    wait(.5)
    for i, character in next, hitE do
        if character == eneH then
            table.remove(hitE, i)
        end
    end
end

Note the truncated comment, this means the other codes to be run and so on.

Rewritten Code


local hitE = {}

script.Parent.Blade.Touched:Connect(function(hit)
	local plr = plrS:FindFirstChild(tool.Parent.Name)
	if hit.Parent:IsA("Model") and hit.Parent:FindFirstChild("Humanoid") and and hit.Parent:FindFirstChild("Enemy") then -- no way you can miss because the debounce is for per enemy
		if hit.Parent.Enemy.Value == true then
			local eneH = hit.Parent.Humanoid

			local found
			for _, character in next, hitE do
				if character == eneH then
					-- some boolean toggle for match
					found = true
				end
			end
			
			if not found then
				table.insert(hitE, eneH) 
				if eneH:FindFirstChild("creator") then
					if eneH.creator.Value ~= plr then
						local creator_tag = Instance.new("ObjectValue")
						creator_tag.Value = plr
						creator_tag.Name = "creator"
						creator_tag.Parent = eneH
					end
				else
					local creator_tag = Instance.new("ObjectValue")
					creator_tag.Value = plr
					creator_tag.Name = "creator"
					creator_tag.Parent = eneH
				end
				local dmg = rand:NextNumber(setting.Minimum_Damage,setting.Maximum_Damage)
				module.DamageIndicator(dmg,hit.Parent.Head.CFrame * CFrame.new(rand:NextNumber(-1,1),2,rand:NextNumber(-1,1)))
				eneH:TakeDamage(dmg)

				wait(.5)
				for i, character in next, hitE do
					if character == eneH then
						table.remove(hitE, i)
					end
				end
			end
		end
	end
end)

Difference Log
Changed all the if statements to more appropriate ones. Also added up the debounce thing.

Sorry for not editing the previous post, but this is a post that is directly the solution.

12 Likes

This section doesn’t seem to toggle.

It doesn’t print “found” for some reason.

Hold up, but it seems like something else is the issue…

					local found
					for _, character in next, hitE do
						if character ~= eneH then
							-- some boolean toggle for match
							found = true
						end
					end
					
					if found then
						print('found')

Big woops, it’s supposed to be == and not found.

Fixed the previous post.

1 Like

Now, this section seems to not fire. (sorry for the trouble xd)

						wait(.5)
						for i, character in next, hitE do
							if character == eneH then
								print('yes')
								table.remove(hitE, i)
							end
						end

Realized that I forgot to use table.insert().

Aw, heck. Updated.

2 Likes

This all seems to work perfectly, My first post here on the dev forums asking a question and I get such good support :smiley:
Thank you for your time.

2 Likes

magnitude will be better tho because it detects many enemys around you