Metatable function problem.

Hi all. I have a problem with a function in a metatable. I have this metatable:

[lua]
local VirtualPlayer = {}
local Methods = {}
VirtualPlayer.__index = Methods
Methods.__id = -1
Methods.__steamid = “Null”
Methods.__type = “VirtualPlayer”

function VirtualPlayer:ReturnID()
return self.__id
end
[/lua]

And then when I do a this:

[lua]
function vplayer:IsValid(vply)
if getmetatable(vply) == VirtualPlayer then
if (vply.__type == “VirtualPlayer”) and (vply:ReturnID() > 0) then – This line have the problem
return true
end
end
return false
end
[/lua]

It says that ReturnID is nil… Any idea?

ReturnID should be declared as being part of Methods, not VirtualPlayer.

Sure? I think I tested that too… Btw I will do again.

I see some issues with your code. Does a vplayer derive from the VirtualPlayer table or from the Methods table? It all looks so mixed up and you can’t really see, which table actually is the metatable and which one shall be the class.

Try this here instead. I wrote it in about 10 minutes and it shall work for you

[lua]VirtualPlayer = {
__type = “VirtualPlayer”, – This value is the same for EVERY virtual-player. Changing it at one player means changing it for all players
}; – Holds all methods for this object.

– Creates a new virtual-player object
function VirtualPlayer:New()
local object = {}; – This will be the actual object, this “VirtulPlayer” consists of
local meta = {
__index = self, – Tells “new” first to index “VirtualPlayer”. If nothing is found, it will use the “object” table
}
setmetatable(object,meta); – Link object with meta.

-- Start defining values for this player here. Changing values here at ONE player means only changing it for this SINGLE player.
object.__steamid = "NULL";
object.__id = -1;

return object;

end

function VirtualPlayer:ReturnID()
return self.__steamid;
end

function VirtualPlayer:IsValid()
if(self.__type == “VirtualPlayer” and self:ReturnID() > 0) then
return true;
end
return false;
end

local vply = VirtualPlayer:New(); – Create a new VirtualPlayer.

– Also some nice additions here:
setmetatable(VirtualPlayer,{__call = VirtualPlayer.New});

– With this line above, you can do cool stuff like calling the table
local vply = VirtualPlayer();[/lua]

Omg, I can’t make my metatable working with __eq. Could someone do an example? Here is my entire metatable:

[lua]local VirtualPlayer = {}
local Methods = {}
VirtualPlayer.__index = Methods
Methods.__id = -1
Methods.__steamid = “Null”
Methods.__type = “VirtualPlayer”

function VirtualPlayer:__len()
return tostring(self:GetID())
end

function VirtualPlayer:__tostring()
return tostring(self.__id)…" virtual player"
end

function VirtualPlayer:__eq(a,b)
Msg(“omg is comparing two things lol”)
if a:IsPlayer() then
return b:GetID() == a:GetNWInt(“aerpid”)
elseif b:IsPlayer() then
return a:GetID() == b:GetNWInt(“aerpid”)
end
if vplayer:IsValid(a) and vplayer:IsValid(b) then
return a:GetID() == b:GetID()
end
return false
end

function VirtualPlayer:__unm()
for k,v in pairs(player.GetAll()) do
if self == v then
return v
end
end
return nil
end

function VirtualPlayer:Online()
if -self then
return true
else
return false
end
end

function VirtualPlayer:__call(id)
self.__id = tonumber(id)
if SERVER then
DB:InitializeVirtualPlayer(self)
if self.Name == nil then
Msg(“There is no data for that id”)
return false
end
end
return self
end

function VirtualPlayer:GetID()
return self.__id
end

vplayer = {}
vplayer.__list = {}
function vplayer:GetByID(id)
return self.__list[id]
end
function vplayer:GetAll()
return self.__list
end
function vplayer:Create(id)
Obj = {}
setmetatable(Obj,VirtualPlayer)
local a,b,c = nil,nil,nil
if type(id) == “string” then
a = string.find(id," ")
a = a or string.len(id)
b = string.sub(id,1,a - 1)
c = tonumber(b)
if c == nil then
error(2,“id is a non-valid string”)
return false
end
elseif type(id) != “number” then
error(“argument only can be a number or string”,2)
else
c = id
end
if c <= 0 then
error(“this number can not be used as id”,2)
end
if self.__list[c] != nil then
return self.__list[c]
end
self.__list[c] = Obj©
if self.__list[c] == false then
error(“there’s no data about that ID”,2)
end
return self.__list[c]
end

function vplayer:IsValid(vply)
if getmetatable(vply) == VirtualPlayer then
if (vply.__type == “VirtualPlayer”) and (vply:GetID() > 0) then
return true
end
end
return false
end
[/lua]

Did you just completely ignore what Avon posted? Use his code, and you can better see what you should be adding metamethods to.

I didn’t ignored. Just I didn’t understand… Sorry.

If you understand what a metatable is and how it works, I’m pretty sure you can understand what Avon posted - especially since he commented it well.

I’m playing with his examples. I will post here if I get it working. Yeah, he commented it well, but I have headache… Sorry.

Your _eq has three parameters instead of two, it’s equivalent to
[lua]function VirtualPlayer.__eq(self, a, b)[/lua]

It should be more like this.
[lua]function VirtualPlayer:__eq(other)
Msg(“omg is comparing two things lol”)
if self:IsPlayer() then
return other:GetID() == self:GetNWInt(“aerpid”)
elseif other:IsPlayer() then
return self:GetID() == other:GetNWInt(“aerpid”)
end
if vplayer:IsValid(self) and vplayer:IsValid(other) then
return self:GetID() == other:GetID()
end
return false
end[/lua]