I've been programming for a long time now, and one question that has plagued me is this. I've been able to find workarounds, but no longer.
I'm creating a terrain generator, and the idea behind it is this: Put nearby terrain parts into a table Put possible terrain locations into a table
If a nearby terrain part has the same location as a possible terrain location, remove it from the table.
Create terrain
Seems simple, right? Ideally one would assume this would work:
for _, nearGridTable in pairs(nearbyGrid) do
for index, nearPositions in pairs(possibilities) do
if nearGridTable == nearPositions then
print("same")
table.remove(possibilities, index)
print("removed")
end
end
end
The issue I run into however is, my print's never run. That has lead me to believe that the nearGridTable is never equaling nearPositions.
On further analysis, there are duplicate values in both table, this for loop is just not getting them properly.
I've had a few ideas on how one might go about fixing it:
Idea 1:
Check the values before I put it into the table
This wouldn't work, as it would be inefficient for my use case.
Idea 2:
use table.sort()
However, that doesn't sort my tables properly (I'm storing vector3 values). I could go about making my own sort function. I've never done this, and so essentially I come before everyone asking, what would you do to compare two tables?
Full code so you understand the context of what I'm working on:
-- Made by Conmmander --
-- terrainCore --
-- Last Edit: 9-2-2018, 2:55 PM --
-- Inititalization --
print("Intialization | "..script.Name)
-- Game Services --
local workspaceService = game:GetService("Workspace")
local playerService = game:GetService("Players")
local lightingService = game:GetService("Lighting")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverStorage = game:GetService("ServerStorage")
local starterGui = game:GetService("StarterGui")
local starterPack = game:GetService("StarterPack")
local chatService = game:GetService("Chat")
-- Game Folders --
local terrainStorage = serverStorage:FindFirstChild("terrainStorage")
local baseTerrain = terrainStorage:FindFirstChild("baseTerrain")
local buildingTerrain = terrainStorage:FindFirstChild("buildingTerrain")
-- Configuration --
local ignoreCordinates = {}
local baseLimit = 100
local yCord = .5
local mingenerationRange = 12
local maxgenerationRange = 15
-- Variables --
local bases = 0
local initialSetup = false
-- Functions --
function countTerrain()
bases = 0
for _, defaultPart in pairs(workspaceService:GetChildren()) do
if defaultPart.Name == "defaultGrid" then
bases = bases + 1
end
end
end
function generateTerrain(player)
local nearbyGrid = {}
local possibilities = {}
if initialSetup == false then
local position = CFrame.new(math.random(math.randomseed(1)), yCord, math.random(math.randomseed(1)))
local clonedBase = baseTerrain.defaultGrid:Clone()
clonedBase:SetPrimaryPartCFrame(position)
clonedBase.Parent = workspaceService
initialSetup = true
end
local debounce = false
countTerrain()
if bases < baseLimit then
local Torso = player.Character.HumanoidRootPart
local base = player.Character.RightFoot
base.Touched:Connect(function(hitPart)
wait(.1)
if debounce == false then
debounce = true
if hitPart.Parent.Name == "defaultGrid" then
if (hitPart.Parent.centerPart.Position-Torso.Position).Magnitude >= mingenerationRange and (hitPart.Parent.centerPart.Position-Torso.Position).Magnitude < maxgenerationRange then
wait(.1)
local debounce2 = false
if debounce2 == false then
debounce2 = true
table.insert(possibilities, hitPart.Parent.centerPart.Position - Vector3.new(0, 0, 30))
table.insert(possibilities, hitPart.Parent.centerPart.Position + Vector3.new(0, 0, 30))
table.insert(possibilities, hitPart.Parent.centerPart.Position - Vector3.new(30, 0, 0))
table.insert(possibilities, hitPart.Parent.centerPart.Position + Vector3.new(30, 0, 0))
print("Insert")
for _, leftPart in pairs(hitPart.Parent.left:GetTouchingParts()) do
print("Called")
if leftPart.Parent.Name == "defaultGrid" then
table.insert(nearbyGrid, leftPart.Parent.centerPart.Position)
print("Insertleft")
end
end
for _, rightPart in pairs(hitPart.Parent.right:GetTouchingParts()) do
print("Called")
if rightPart.Parent.Name == "defaultGrid" then
table.insert(nearbyGrid, rightPart.Parent.centerPart.Position)
print("Insertright")
end
end
for _, nearGridTable in pairs(nearbyGrid) do
for index, nearPositions in pairs(possibilities) do
if nearGridTable == nearPositions then
print("same")
table.remove(possibilities, index)
print("removed")
end
end
end
for _, position in pairs(possibilities) do
local clonedBase = baseTerrain.defaultGrid:Clone()
clonedBase:SetPrimaryPartCFrame(CFrame.new(position))
clonedBase.Parent = workspaceService
end
end
debounce2 = false
end
end
end
wait(.2)
debounce = false
end)
end
end
-- Code --
playerService.PlayerAdded:Connect(function(addedPlayer)
addedPlayer.CharacterAdded:Connect(function(addedCharacter)
generateTerrain(addedPlayer)
end)
end)
-- Loop --
while true do
wait(5)
for _, players in pairs(playerService:GetPlayers()) do
generateTerrain(players)
end
end
EDIT:
Some nice person I spoke with yesterday sent me this as a method of sorting tables, but how would I use it? (I'm not very familiar with sorting tables).
local function unordered_tostring_equals(array_1, array_2)
-- making count_diffs[unknown] return 0 instead of nil
-- I usually I have have a function for this: count_diffs = DefaultedTable(0)
local count_diffs = setmetatable({}, {__index = function()
return 0
end})
-- adds 1's counts
for _, v in ipairs(array_2) do
local str = tostring(v)
count_diffs[str] = count_diffs[str] + 1
end
-- subtracts 2's counts
for _, v in ipairs(array_1) do
local str = tostring(v)
count_diffs[str] = count_diffs[str] - 1
end
-- if the same tostrings has a different count, it's a different table
for _, count in pairs(count_diffs) do
if count ~= 0 then
return false
end
end
return true
end

2 comments
Yes I did, there are identical Vector3 values.
nvm i re-read your post and found out you said that already