Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Best way to learn advanced Lua?

I am a fairly intermediate/advanced "scripter" in RBX.Lua and I have been wanting to move on to more advanced topics such as environments and metatable manipulation. Though, everywhere I look, it's mostly just the bare essentials, it doesn't teach you what it's useful for or how to use it in general. So, I was just hoping someone here could point me in the direction of something that's actually worthwhile. Thanks!

1 comment

0

The wiki has a whole page on metatables.

5 answers

Roblox wiki, Youtube videos like Friaza Peaspod and many more. Even try understanding free model scripts.

On metatables and the environment. First, we'll start with metatables.

A metatable is a table, just like any other, except that it can be assigned to another table to give the table more functionality. Metatables can be given specific keys called metamethods to control what happens when you, say, try to get something from the table that isn't there. That can be achieved with the __index metamethod. The __index method can be a table/userdata, or it can be a function.

Example 1: __index as a table

t = {a = 1, b = 2, c = 3}

mt = {
	__index = {d = 4}
}

setmetatable(t, mt)

print(t.a, t.b, t.c, t.d) --"d" isn't in the table, but it's in the __index, so we can still print it.

Example 2: __index as a userdata

t = {a = 1, b = 2, c = 3}
part = Instance.new("Part")
mt = {__index = part}
setmetatable(t, mt)
print(t.BrickColor) --There's no BrickColor in t, but there's a BrickColor in part.

Example 3: __index as a function with the table and key as arguments

t = {a = 1, b = 2, c = 3}
mt = {
	__index = function(self, key)
		return "Key: "..key.." was not found."
	end
}
setmetatable(t, mt)
print(t.d)

There's also __newindex, a function that controls what happens when you try to set a new key in the table.

t = {a = 1, b = 2, c = 3}

mt = {
	__newindex = function(self, key, value)
		--[[Since doing "self[key] = value" would trigger __newindex again
			and create an infinite loop, we have the rawget/rawset functions to
			prevent the above from happening.
		--]]
		rawset(self, key, value)
		print(key.. " was appended with a value of "..value)
	end
}

setmetatable(t, mt)

t.a = 5
t.b = 4
t.c = 3
t.d = 2
t.e = 1

The environment is a table of every global variable that the current stack level, or a given function, has access to. When you create a (non-localized) variable, it gets stored in the environment. You can access the script's environment with getfenv.

a = 1
print(a)
print(getfenv().a)

getfenv().b = 2
print(getfenv().b)
print(b)

We can alter the environment with setfenv.

setfenv(1, {a = 1, b = 2, c = 3})
print(a)

Notice how we can't print anything, because print was in our old environment, and now we have a new environment. How do we fix that? We use __index.

env = getfenv()
mt = {__index = env}
setfenv(1, setmetatable({a = 1, b = 2, c = 3}, mt))
print(a) --Now it works, since we brought the old environment with us in the __index.

And that's the basics of it. From there, you just build on it with your creativity.

This discussion is preserved as it was. New answers, comments, and votes are closed.