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

Metatable Making a Function Nil?

Asked by 9 years ago

I started learning Metatables from a YouTube series on Lua this morning and I have run into a peculiar error while practicing Metatables. I made an advanced table previously and it had worked but it appears that the Metatable has caused it to break and I can't tell why. It prints out the coordinates and names correctly and then breaks when it attempts to connect to the move function. An explanation of what is going on and how it could be fixed would be greatly appreciated.

Error:

Workspace.Script:60: attempt to call field 'move' (a nil value)

Player = {
        x = 0, y = 0, z = 0,
        name = "",

        mt = {},

        new = function()
                local p = {}
                setmetatable(p, Player.mt)
                return p
        end,

        move = function(p, x, y, z)
                p.x = p.x + x
                p.y = p.y + y
                p.z = p.z + z
        end
}

Player.mt.__add = function(p1, p2)
        local p = Player.new()
        p.x = p1.x + p2.x
        p.y = p1.y + p2.y
        p.z = p1.z + p2.z
        return p
end

Player.mt.__sub = function(p1, p2)
        local p = Player.new()
        p.x = p1.x - p2.x
        p.y = p1.y - p2.y
        p.z = p1.z - p2.z
        return p
end

Player.mt.__eq = function(p1, p2)
        return p1.x == p2.x and p1.y == p2.y and p1.z == p2.z
end

Player.mt.__tostring = function(p)
        return "("..p.x..", "..p.y..", "..p.z..")"
end

p1 = Player.new()
p2 = Player.new()

p1.x = 20
p1.y = 10
p1.z = 0
p1.name = "Player1"

p2.x = 40
p2.y = 80
p2.z = 120
p2.name = "Player2"

print(tostring(p1), p1.name)
print(tostring(p2), p2.name)

p1.move(p1, 50, -40, 60)
p2.move(p2, 30, 10, -10)

print(p1.x, p1.y, p1.z)
print(p2.x, p2.y, p2.z)

p3 = p1 + p2
p4 = p2 - p1

print(p3)
print(p4)
print(p3 == p4)

1 answer

Log in to vote
1
Answered by
ImageLabel 1541 Moderation Voter
9 years ago

Your problem is that your function new, returns a newly created table instead of the original, Player table, in which move is located. Therefore, move does not exist in the table returned by new. You can easily fix that without changing much of your code by doing the following.


You could use the __index metamethod to refer back to the prototype table Player. The event itself fires when table[key] is indexed. You would then configure it to return the function move.

Player.mt.__index = function (_, key)
    return Player[key] 
end

The first argument represents the table being indexed, which we do not care for, and the following argument is the indexed key.

0
Thank you, it worked. FearMeIAmLag 1161 — 9y
Ad

Answer this question