Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Multidimensional array is saying "attempt to index field '?' (a nil value)"

Asked by 5 years ago
Edited 5 years ago

I've tried to figure this out for a while now and just can't find the error. There is a comment above the line of code that triggers the error. Basically I'm trying to store the position data within a table (whenever the player clicks on certain parts) that can be quickly accessed for later use (I have no need to sort the data, and the data is only ever used for comparison purposes). Here are some code snippets that affect what I'm trying to do:

local player = game:GetService("Players").LocalPlayer
local equipped = false
local depressStopped = false
local part = ""
local mouse = player:GetMouse()
local distance = 0
local tool = script.Parent
local copy = ""
local copyPosition = ""
local copyPositionX = game.Workspace.Parttay.Position.X
local copyPositionY = game.Workspace.Parttay.Position.Y
local copyPositionZ = game.Workspace.Parttay.Position.Z
local masterTable = {

[copyPositionX] = {[copyPositionY] = {[copyPositionZ]={copyPositionZ}}}

}

--[[TABLE LAYOUT: with example data

masterTable     copyPositionX   copyPositionY   copyPositionZ       
                200             150             200         =200x150y200z
                                100             200         =200x100y200z
                300             150             200         =300x150y200z
                400             100             150         =400x100y150z

*note: the only data that can be directly accessed is the copyPositionZ
--]]
tool.Equipped:connect(function()
    equipped = true
    while equipped do
        pcall(function()
            distance = (mouse.Target.Position - game.Workspace[player.Name].Head.Position).magnitude
            if mouse.Target:IsDescendantOf(game.Workspace.ConstantBlocks)  and distance < 20 then
                part = mouse.Target         
                position = part.Position
            --other code
            end
        end)
    end
end)

tool.Unequipped:Connect(function()
    equipped = false
end)
mouse.Button1Up:connect(function()
    depressStopped = true
end)

mouse.Button1Down:connect(function()
    while equipped == true and depressStopped == false do
        if part:IsDescendantOf(game.Workspace.ConstantBlocks) and distance < 20 then
            --part comes from the equipped function
            copyPositionX = part.Position.X
            copyPositionY = part.Position.Y
            copyPositionZ = part.Position.Z
            print(copyPositionX, copyPositionY, copyPositionZ)
            --THE FOLLOWING LINE CAUSES THE ERROR!
            masterTable[copyPositionX][copyPositionY][copyPositionZ] = copyPositionZ
        --other code
        end
    end
    depressStopped = false
end)

I'm still kinda new to this and would appreciate any pointers as well!

[EDIT]

I may just misunderstand how it works, but this code works just fine:

part = game.Workspace.Parttay
copyPositionX = part.Position.X
copyPositionY = part.Position.Y
copyPositionZ = 0
print(copyPositionX, copyPositionY, copyPositionZ)
local masterTable = {

[copyPositionX] = {[copyPositionY] = {[copyPositionZ] = {copyPositionZ}}}

}
masterTable[copyPositionX][copyPositionY][copyPositionZ] = copyPositionZ
print(masterTable[copyPositionX][copyPositionY][copyPositionZ])
0
First of all you should get rid of those dots in empty lines Tymberlejk 143 — 5y
0
That's to show there is more code, but I can separate the code snippets if it makes it easier. SteelMettle1 394 — 5y
0
I wasn't sure if this was a simple error on my part or not, so I didn't have every variable declared in the snippets. I just added all of them, I really am stumped on this though. SteelMettle1 394 — 5y

2 answers

Log in to vote
0
Answered by 5 years ago

In Lua, you can't declare a multidimensional array and then have it work for all combination of values, you have to make a new table for every index. That is, on line 15, you declare your masterTable, but you only initialize the tables needed for one coordinate.

If you wanted a 10x10x10 array with integer values, you could do this:

local t = {}
for x = 1, 10 do
    t[x] = {}
    for y = 1, 10 do
        t[x][y] = {}
        for z = 1, 10 do
            t[x][y][z] = 0
        end
    end
end

However, if you're wanting to put in arbitrary coordinates (ie they involve decimals or arbitrarily large integers), you'll want to use a function that sets up the tables on an as-needed basis (since you can't possibly make enough tables to cover all possible decimals):

local masterTable = {}
function store(x, y, z, value)
    local tx = masterTable[x]
    if not tx then
        tx = {}
        masterTable[x] = tx
    end
    local ty = tx[y]
    if not ty then
        ty = {}
        tx[y] = ty
    end
    ty[z] = value
end
function get(x, y, z)
    return masterTable[x] and masterTable[x][y] and masterTable[x][y][z]
end
function delete(x, y, z) -- Delete the value stored at x,y,z and release memory if possible
    if get(x, y, z) == nil then return end
    local tx = masterTable[x]
    tx[y][z] = nil
    if not next(tx[y]) then
        tx[y] = nil
        if not next(tx) then
            masterTable[x] = nil
        end
    end
end
store(1, 2, 3, true)
print(get(1, 2, 3)) -- true
print(get(10, 10, 10)) -- nil, but doesn't error (unlike saying masterTable[10][10][10] here)
delete(1, 2, 3)
print(masterTable[1]) -- nil -- tables have been removed to save memory

I noticed you store a value identical to your 'z' coordinate - if there's nothing else being stored, that's redundant and you can remove the value (just store 'true' for example). The equivalent in a 1D table:

local t = {}
t[5] = 5 -- redundant
t[5] = {5} -- redundant and harder to access the '5' at the end -- this is what you appear to be doing
t[5] = true -- all you need
0
This will take me a bit to digest, but I think you may have solved it. The reason I added stored the key as the data is I needed it to compare, but with your method I could just compare the value in t[5] to true (since only those coordinates will allow it) SteelMettle1 394 — 5y
0
Thank you for your time/answer SteelMettle1 394 — 5y
Ad
Log in to vote
0
Answered by
clc02 553 Moderation Voter
5 years ago

For your error, since you didn't list a line it occurred on I can't tell you what line it happens on, but you're attempting access a table[x][y] where [x] doesn't exist. This usually happens if you're assuming the array is going to be a 5x5 array so you try to access table[5][5] without first making table[1] through table[5] empty arrays first.

function initialize2d(x, y, default)
  local t = {}
  for i = 1, x do
    t[i] = {}
    for j = 1, y do
      t[i][j] = default
    end
  end
end

Answer this question