Array comparer inaccurate

Hey there!

For context
I’m creating a placement system to build structures using a custom position system
The easiest way of imagining it is basically just a coordinate plane. You start building at (0, 0), expand outwards in any direction from that position (0, 1), and more grids become available as you start building from that. Anyways, that’s not important.

The main I’m running into is enabling each available grid
I’ve tagged each possible grid where the player can place an item, and I’m then putting each element into an array, that will be compared against each element to determine if the positions are the same
This is so that multiple grids are not overlapping each other, and so that the player can place exactly 1 item per grid
Below is the main script:

function isValid()
	
	local check = {}
	itemsToBe = {}

	for _, v in pairs(cs:GetTagged("comparingBoundaries")) do
		table.insert(itemsToBe, v)
	end
		
	for _, v in pairs(itemsToBe) do
		local xV = v:FindFirstChild("xCoord")
		local yV = v:FindFirstChild("yCoord")
		
		for _, j in pairs(itemsToBe) do
			if v and j and v ~= j then
				local xJ = j:FindFirstChild("xCoord")
				local yJ = j:FindFirstChild("yCoord")
				
				if xV.Value == xJ.Value and yV.Value == yJ.Value then
					determineIt(v, j, itemsToBe)
				end
			end
		end
	end
end

In the below screenshot, you can see that this is sometimes inaccurate and that the available grids overlap parts that are already existing


The odd part is that the inconsistencies vary. When you place down the item and pick it up again, the available grids shift. Sometimes it’s accurate, sometimes it’s not. In this case, it was not accurate

The main issue might be the way I’m determining which grid gets to show and which one doesn’t once they overlap, as I’m just using a random number generator

function determineIt(x, y, array)
	local xyz = math.random(1, 2)
	if x.Name == "main" then
		if (table.find(array, y)) then
			table.remove(array, table.find(array, y))
		end
	elseif y.Name == "main" then
		if (table.find(array, x)) then
			table.remove(array, table.find(array, x))
		end
	else
		if xyz == 1 then
			if (table.find(array, y)) then
				table.remove(array, table.find(array, y))
			end
		else
			if (table.find(array, x)) then
				table.remove(array, table.find(array, x))
			end
		end
	end
end

Wow, that was a lot, but hopefully I was detailed enough to explain my issue :sweat_smile:
Any help/suggestions are appreciated greatly!

this is still unsolved…
ANY help is appreciated :pray::heart:

Am I correct in assuming that the available and filled spaces are stored inside the same array?

yes

onlythirtycharactersareallowed

hmm, what happens when you comment out the code inside the else statement

im assuming you mean in the determineIt function
the if/else statement is needed to give planks precedent, so if the else statement was removed, the function would break entirely

function determineIt(x, y, array)
	local xyz = math.random(1, 2)
	if x.Name == "main" then
		if (table.find(array, y)) then
			table.remove(array, table.find(array, y))
		end
	elseif y.Name == "main" then
		if (table.find(array, x)) then
			table.remove(array, table.find(array, x))
		end
	else
--[[
        if xyz == 1 then
			if (table.find(array, y)) then
				table.remove(array, table.find(array, y))
			end
		else
			if (table.find(array, x)) then
				table.remove(array, table.find(array, x))
			end
		end
]]--
	end
end 

(Accidental Edit)

yes, that would cause the script to break

if one of the two items with the same coordinates being compared is a plank, then it needs to remove the other

the else is if neither of the two items are planks, meaning if neither of them are planks, then it wouldn’t remove one of the items from the array, thus causing the overlap to occur no matter what

1 Like

I found a possible solution to the problem.

Instead of removing the instance from the array, set it to a null value, and loop through afterwards to remove the null values.

unfortunately, this did not solve the issue
the reason most likely is the way that I’m comparing values for the array

after you run the function, can you loop through the array and output all of the x and y coordinates

for _, v in pairs(itemsToBe) do
	local xV = v:FindFirstChild("xCoord")
	local yV = v:FindFirstChild("yCoord")
	print(xV, yV)
end

i’m assuming you mean v:FindFirstChild(“xCoord”).Value
this is the result of an accurate boundary display

Screenshot 2024-07-14 at 5.37.38 PM

I just had an idea, can you print the name next to it as well, what does it look like for an inaccurate one?

it doesn’t look for an innacurate one per say
it’s just that sometimes it correctly displays the boundaries, sometimes it doesn’t
printing the name is useless, as they all have the same name

Maybe its something to do with the boundary display script

That is exactly what the whole issue is :sweat_smile:

I mean the part that highlights the area

I decided to test the script on a local file, I got it to work by using the dermineIt() function to read one of the items names, and return its index based on that.

function determineIt(v, i, j)
	
	if v.Name == "main" then
		return i
	end
	
	return j
	
end

and then having the isValid() function return an array with true at the index of every part that is to be removed, using the dermineIt() function, and obtaining the index of the parts from the loop

function isValid()

	local check = {}
	local shouldDestroy = table.create(5, false)

	local itemsToCompare = {}
	for _, v in pairs(cs:GetTagged("comparingBoundaries")) do
		table.insert(itemsToCompare, v)
	end

	for i, v in pairs(itemsToCompare) do
		
		local xV = v:FindFirstChild("xCoord")
		local yV = v:FindFirstChild("yCoord")

		for j, u in pairs(itemsToCompare) do
			
			if v and u and v ~= u then

				local xU = u:FindFirstChild("xCoord")
				local yU = u:FindFirstChild("yCoord")
				
				if xV.Value == xU.Value and yV.Value == yU.Value and j > i then
					shouldDestroy[determineIt(v, i, j)] = true
				end
				
			end
		end
	end
	
	return shouldDestroy
	
end

sorry, but i’m a little bit confused to this script
what exactly is the shouldDestroy array used for?
just wondering how its working so i can integrate into the full scope of the program

sorry about the shouldDestroy variable, I was destroying the overlapping parts, but the variable name doesn’t matter, a more suitable name for it might be isOverlapping
it should work close to your original, except it returns a Boolean array with true at every index that would have been removed from the array

I also realized that this:

can be replaced by an empty array

You can then loop through the array and if the value is true look up the object via its index.