Issues with table.Find?

Hi - I’m starting to practice and learn .table within ROBLOX however I’ve hit a snap with my collision system?

The way it’s intended to work is: using table.find to check if the HitHumanoid is already within the Table, if not - It inserts it. However, it seems to be inserting it multiple times, regardless.

Secondly, I use the ‘true’ and ‘false’ of [2] to dictate whether Damage has already been dealt to a Humanoid in each swing, this is to prevent multi-damage being dealt where it’s not needed. Although I’m still facing this issue.

	function __()
		Debounce = true; _Hit = {}
		local anim = Player.Character:WaitForChild("Humanoid"):LoadAnimation(script["anim"])
		anim:Play()
		
		Multi = game:GetService("RunService").Heartbeat:Connect(function()
			local _Touching = Tool:WaitForChild("Hitbox"):GetTouchingParts()
			for _,i in pairs (_Touching) do
				if i.Parent:FindFirstChild("Humanoid") ~= nil then
					local E = table.find(_Hit, {i.Parent["Humanoid"], false})
					if E then else
						if i.Parent == Player.Character then else
							table.insert(_Hit, {i.Parent["Humanoid"], false})
						end
					end
				end
			end
			___()
		end)
		
		repeat wait(.75) until anim.IsPlaying == false
		Debounce = false
		Multi:Disconnect()
		
		for _,i in pairs (_Hit) do
			print(i[1]) print(i[2])
		end
		
	end
	
	function ___()
		for _,i in pairs (_Hit) do
			if i[2] == true then
			else
				i[2] = true
			end
		end
	end
1 Like

Dont call functions “__” :worried:

Anyway, your problem is that

({} == {}) 

evals to false, because table comparison doesnt look at the table contents. Two tables are never equal, unless you overwrite the __eq metamethod.

The table that you insert and the table that you search for are not equal, never can be. So the table.find call always returns nil.

1 Like

Sorry, the ___ is literally just place holders right now, by no means is it any sort of final product.

Thanks! - How could I sort this to function() to allow for some sort of check that will dictate whether or not damage has occurred in the time of a swing?

1 Like

Could always create your own function to iterate through _Hit and check if the contents of the array are the same as the one you’re looking for:

function Equals(Array1, Array2)
    for Index, Value in ipairs(Array2) do 
        if (not (Array1[Index] == Value)) then --// If at the same index in Array1 is not the same as Array2
            return false;
        end
    end

    return true; --// If all pass, return true
end

function IsInHit(Array)
    for _, HitArray in ipairs(Array) do
        if (Equals(HitArray, Array)) then
            return true; --// If they're the same, return true
        end
    end
end

FYI:

This can be bad on performance, I’d recommend using the :Wait() method on anim.Stopped since that yields entirely until the event is fired.

1 Like

Instead of using an array like youre doing now, you could use a dict that maps humanoids to a bool indicating whether or not that humanoid has already been hit.

E.g.

local hitHumanoids = {}

...

if not hitHumanoids[humanoid] then
    hitHumanoids[humanoid] = true
end

...

--The actual bool is moot because only humanoids that were hit had the bool set, and in that case it would have been set to true
for h, _ in pairs(hitHumanoids) do
    print(h)
end
1 Like

Or make your own search function that uses a predicate instead of a value to compare against:

function predicateFind(t, p)
    for k, v in pairs(t)
        if p(v) then
            return k, v
        end
    do
end

function sameValueAtKey(a, b, key)
    return a[key] == b[key]
end

then you can replace the call to table.find with this:

local E = predicateFind(_Hit, function(v)
    return sameValueAtKey(
        {i.Parent["Humanoid"], false},
        v,
        1
    )
end)

it looks ugly bevause it is :stuck_out_tongue: but its closer to your original approach