Problems w/ Static Module Event

I’m trying to create a quest system and have ran into a bit of a problem with events. I wish to have a static BindableEvent that fires when any quest is accepted by any player.

When I pass self from the module to the event, for some reason it’s not returning the object I expect, but what seems to be another instance of my class.

ServerScript:

local Quest = require(script.Parent:WaitForChild("Quest"))

local testQuest = Quest.new("Quest Test")

Quest.Accepted:Connect(function (quest:Quest, plr:Player)
	print(quest.Title == testQuest.Title) -- true
	print(quest == testQuest) -- false?!
end)

local function playerAdded(plr:Player)
	testQuest:Accept(plr)
end

game.Players.PlayerAdded:Connect(playerAdded)

Module:

local Accepted = Instance.new("BindableEvent")

local Quest = {
	Accepted = Accepted.Event,
}

Quest.__index = Quest

function Quest.new(title:string)
	local self = { Title = title }
	setmetatable(self, Quest)
	return self
end

function Quest:Accept(plr:Player)
	Accepted:Fire(self, plr)
end

return Quest

I’m stumped as to why this is happening. Any suggestions are appreciated.

You can’t pass self from client to server and vice versa.

This is only on the server. If not, I would expect the value passed to be nil.

Firstly, you aren’t even returning the metatable, but only the table itself.
It should be written like such.

function Quest.new(title:string)
	local self = setmetatable({ 
    Title = title 
    }, Quest);

	return self;
end;

I believe the problem is that it uses a BindableEvent, this generates a copy of the table object rather than the original object reference itself.

If you print it out with the table reference enabled you should find that it’s different.

Try using a Signal module instead.

It doesn’t make no difference.

For real?

maxcharactersthisisannoying

Yeah that’s what my original message said, but I deleted it because I was unsure, due to me passing tables server to server in the past.

(Obviously not your exact words lol)

1 Like

I believe this is what I was looking for. Thanks!

Still don’t quite understand why it works that way, but okay. It looks like the simplest approach would be pass a string that can reference the object from the module itself.

ServerScript:

local Quest = require(script.Parent:WaitForChild("Quest"))

local testQuest = Quest.new("Quest Test")

Quest.Accepted:Connect(function (uid:string, plr:Player)
	local quest = Quest.getQuestFromId(uid)
	print(quest == testQuest)
end)

game.Players.PlayerAdded:Connect(function (plr:Player)
	testQuest:Accept(plr)
end)

ModuleScript:

local Accepted = Instance.new("BindableEvent")

local questTable:{[string]:Quest} = {}

local Quest = {
	Accepted = Accepted.Event
}

function Quest.getQuestFromId(uid:string)
	return questTable[uid]
end

Quest.__index = Quest

function Quest.new(uid:string)
	local self = { uid = tostring(uid):sub(1, 50) }
	questTable[uid] = setmetatable(self, Quest)
	return self
end

function Quest:Accept(plr:Player)
	Accepted:Fire(self.uid, plr)
end

return Quest

You just need objects to have references from both scripts.