Rochet2
Moderator / Eluna Dev
luathread
I thought to post a little thread about scripting with lua.
Posting some special things you can, should and should not do and why.
I apologize if I appear messy or not understandable at some points : |
This thread has nice comments and tips in the replies as well!
Do remember to read them as well
NEVER save an ?object? overtime! (boss = unit is a no no)
Ok, .. there are some exceptions.. (see next post for an example of a nice workaround )
But basically you should never save a player for example to a variable you are not using instantly.
When the player logs out, the variable wont become nil. On C++ side the player is a pointer, which will be "valid" (not NULL), but it points to an area that no longer has player data in it.
This means that when a player logs out and you use the player object still after that, there is a possibility for crashing and having bad method reads and more.
This problem can be avoided in certain ways, but I would rather not use them as they would disable certain functionality and possibilities. Be smart, dont do it
Should use guids instead. (GetGUID)
Use GetGUIDLow! not GetGUID
This may sound a little like I am contradicting myself with what I said before..
But GUID is a (number as a) string, and as such, it is "worse" for tables as a key.
It is also bigger than GUIDLow, and it also can not and should not be used in the database.
When handling stuff in the code, it is fine to use GUID instead of GUIDLow though. GUIDLow is the ID used in database tables for player, creature etc!
Check out the differences with GUID and low GUID Also see the global methods for them
Collision in scripts is seen very often.
Note that the script is not bound to a creature. It is a global script.
This means that if you use a variable like:
local spawned = false
It is just one variable. This means that multiple NPCs that run an event to change or check that variable use the same variable.
So, for example if a boss script that sets that variable to true when spawning adds, other instances of the same raid or dungeon where the boss is wont get adds at all, since the variable says that they are already spawned when checked by the script.
You should solve this problem for example by saving data to a lua table with the instance ID or creature guid low for example (boss guid)
Localize your variables and functions!
You should always localize your variables. Mostly you can just say local x = 2 and so, but sometimes you may need to declare a variable local before using it.
This can be achieved by doing for example:
This code will set a local variable, but you wont hit a problem with the variable being local like when trying similar to this:
Localizing your functions may be important.
You can do this in a few ways. One of the ways is to just declare that it is local when defining or declaring the function like so:
local function testFunction()
With this way you may run into problems when trying to use the function that is local before it is defined though.
You can solve this problem by using the option 2 or by declaring the functions local before using them, like this:
Another way is to store all functions (and variables) inside a table, which then can be made local.
Localizing variables and functions is needed to prevent them from being overwritten or from overwriting functions and variables with the same name.
They also wont take up memory by being global when used just in one function for example.
Often scripts tend to use unique function names and as such, mostly people do not use local functions. Local functions are said to be faster though. (source?)
What if I need to pass more variables than a function can receive ?
In some situations you might want to pass additional arguments to functions.
This is often needed with timed events. This is also a useful trick for some situations
Lua allows you to create functions inside a function. You can also store functions to a variable and tables and so.
Actually the function defining syntax is just a syntactic sugar to:
local myFunction = function(eventId, delay, calls, customVar) print(customVar) end
I thought to post a little thread about scripting with lua.
Posting some special things you can, should and should not do and why.
I apologize if I appear messy or not understandable at some points : |
This thread has nice comments and tips in the replies as well!
Do remember to read them as well
NEVER save an ?object? overtime! (boss = unit is a no no)
Ok, .. there are some exceptions.. (see next post for an example of a nice workaround )
But basically you should never save a player for example to a variable you are not using instantly.
When the player logs out, the variable wont become nil. On C++ side the player is a pointer, which will be "valid" (not NULL), but it points to an area that no longer has player data in it.
This means that when a player logs out and you use the player object still after that, there is a possibility for crashing and having bad method reads and more.
This problem can be avoided in certain ways, but I would rather not use them as they would disable certain functionality and possibilities. Be smart, dont do it
Should use guids instead. (GetGUID)
Use GetGUIDLow! not GetGUID
This may sound a little like I am contradicting myself with what I said before..
But GUID is a (number as a) string, and as such, it is "worse" for tables as a key.
It is also bigger than GUIDLow, and it also can not and should not be used in the database.
When handling stuff in the code, it is fine to use GUID instead of GUIDLow though. GUIDLow is the ID used in database tables for player, creature etc!
Check out the differences with GUID and low GUID Also see the global methods for them
Collision in scripts is seen very often.
Note that the script is not bound to a creature. It is a global script.
This means that if you use a variable like:
local spawned = false
It is just one variable. This means that multiple NPCs that run an event to change or check that variable use the same variable.
So, for example if a boss script that sets that variable to true when spawning adds, other instances of the same raid or dungeon where the boss is wont get adds at all, since the variable says that they are already spawned when checked by the script.
You should solve this problem for example by saving data to a lua table with the instance ID or creature guid low for example (boss guid)
Localize your variables and functions!
You should always localize your variables. Mostly you can just say local x = 2 and so, but sometimes you may need to declare a variable local before using it.
This can be achieved by doing for example:
Code:
local testvar
if(condition) then
testvar = true
else
testvar = false
end
Code:
if(condition) then
local testvar = true
else
local testvar = false
end
-- testvar is nil here :(
You can do this in a few ways. One of the ways is to just declare that it is local when defining or declaring the function like so:
local function testFunction()
With this way you may run into problems when trying to use the function that is local before it is defined though.
You can solve this problem by using the option 2 or by declaring the functions local before using them, like this:
Code:
local testFunc
-- code
function testFunction() -- code
Code:
local T = {}
function T.MyFunction()
-- code
end
T.SomeVar = false
They also wont take up memory by being global when used just in one function for example.
Often scripts tend to use unique function names and as such, mostly people do not use local functions. Local functions are said to be faster though. (source?)
What if I need to pass more variables than a function can receive ?
In some situations you might want to pass additional arguments to functions.
This is often needed with timed events. This is also a useful trick for some situations
Code:
local function myFunction(eventId, delay, calls, customVar)
print(customVar) -- prints 123
end
CreateLuaEvent(function(a,b,c) myFunction(a,b,c, 123) end, 5000, 0)
Actually the function defining syntax is just a syntactic sugar to:
local myFunction = function(eventId, delay, calls, customVar) print(customVar) end
Last edited: