From Multi Theft Auto: Wiki
Jump to: navigation, search

Notice to whoever stumbles upon this page: I am at best an amateur Lua scripter. These are just some notes I have saved for myself of things I have learned along the way for quick reference if I forget something.

Nesting functions: Remember that functions are variables. ie if you nest a function on a render event, each loop that function is re-created again. The code in the function may not run, but the function variable is re-created every time. This has nothing to do with being local. Functions are only local if you specify, otherwise they are global. You can still nest them, just do an "if not" check to see if they have been created yet. This can help you keep the code in order instead of jumping all over the place.

Timed set of instructions:

setTimer (function()
	outputChatBox ("test")
end, 250, 1)

Secret Variables<br\> getRootElement()= root<br\> getResourceRootElement() = resourceRoot<br\> <br\> screwed myself over with a very old problem... do NOT use root most times. ie onResourceStop under root for example would trigger when ANY script stops. You only need root when you have something that handles all vehicles for some purpose or something like that. Note that onClientRender or onClientPreRender require root. They don't make sense and do not work otherwise. There is only 1 render.

Use of type()<br\> Returns the type of its only argument, coded as a string. The possible results of this function are "nil" (a string, not the value nil), "number", "string", "boolean", "table", "function", "thread", and "userdata".

Nested function for nicely structured timer that will have the source arg preserved when triggered:

    function PlayerDamage ( attacker, weapon, bodypart )...
    function wheeeeeeee (source)
            setPedAnimation (source, "ped", "getup", 1, false, true, false, false )
    setTimer ( wheeeeeeee, 2500, 1, source )

Use of ... and the hidden 'arg' table for variable amount of arguments

function test(...)
	for k,v in ipairs(arg) do
		outputChatBox ( v )
test("hi", "ho", "the", "deere", "o" )
  • Meta order is important! Remember everything is one big code list when compiled. Utilities should go first!

Finite loops:

use for variable,nth do ... end or for i=1,nth do ... end --USE THIS WHEN POSSIBLE
while blah <= nth do when possible. --ONLY WHEN NEEDED. Minimize infinite loop capability.

something can serve as false, 0, etc. to help with pulling option stuff from users or general error compensation

blah = getSomething(...) or something
--or say prevent the need of if statement when declaring variables...
someTable = someTable or {}

Lua's secret global table... this is how you would refer to a variable, knowing its name through the use of other variables, such as a for k,v statement that makes a number attached to a static string


Using 1 line of code for 2 lines (bad practice!):

outputChatBox("hi") outputChatBox("there") outputChatBox("sir")
hi = "hi"; there = "there"; sir = "sir"--for assignment stuff

bindKey Lesson:

bindageB = function() outputChatBox ( "bindageB" ) end
bindKey ( "F1", "down", function (bindageA) outputChatBox("bindageA") end )
bindKey ( "F1", "down", bindageB )
unbindKey ( "F1", "down", bindageA )--This would unbind everything from F1! bindageA is nil. You must use 2 lines as shown with bindageB.
unbindKey ( "F1", "down", bindageB )--This only removes bindageB. Proper.

A short piece about addEventHandler: addEventHandler is like a filter mostly... its to trigger on specific things. You could create fake parent elements (tree branches) and move elements out of their trees into the dummy tree, so only they call a function. They could also be got by getElementsByType. root is defined by default in MTA as the root of the resource's element tree. That means all peds, vehicles, objects, everything will trigger an event handler. The one place where it is very significant is GUI elements. Since their use is mainly a bunch of clicking, you can see the need to isolate GUI elements with their own event handlers, vs. a massive onClientGUIClick if statement.

When using bindkey, just make it all filter into 1 function and do some checks. Don't be ignant.

My old LUA Information, Tips, and Tricks from the main page! Deleted revision of LUA Information, Tips, and Tricks (as of 21 September 2007, at 07:14) by Ransom

This may possibly be a brief tut in the future trying to get people familiar with things like tables, xml, and other 'scary' stuff :P

  • Appending two Strings: .. Will append a string to another string or varible. This could for example show who has joined a server by appending joining text and joining it to another string which reads a varible (for this example, called playerstring) that sees what player has joined: playerstring.."has joined the server"
  • Script Commentation (--): -- Denotes script commentation. This is for taking notes on your script and will not be read by the script. Everything after -- on the same line will be ignored unless you surround the comment like so: --[[like this]], which allows you to comment somewhere besides the end of script lines.
  • Using strings (""): Is used to specify a string of text, rather than a varible. Quotes must surround your text on functions that have a text argument.
  • Usage of == and =: Two equal signs (==) are used to compare and see if two varibles are equal. One equal sign (=) sign is used to set a varible after the sign.
  • Optional Arguments: You do not have to specify all arguments for some functions. Optional functions are enclosed with [ ] in the syntax display. They are also explained under the "Optional Arguments" heading rather than the "Required Arguments" heading. All the required arguments will always come before optional arguments. You may specify any amount of the optional varibles, but required arguments must always be assigned. You may also choose to skip assigning a value to an optional argument by using "nil" to leave it unassigned and move to the next argument. I will use the following function in the examples (which is a more rare type of function with no required varibles):
textitem textCreateTextItem ( [string text, float x, float y, string priority, int red, int green, int blue, int alpha, float scale] )

Using only the required arguments:

scoregrove = textCreateTextItem ( "Display this as text", 0.075, 0.215 ) --I only wanted to display that text at x,y position on the screen

Using optional arguments after an optional argument you do not want to specify:

scoregrove = textCreateTextItem ( "Display this as text", 0.075, 0.215, nil, 70, 145, 0, 255,  1.8  ) --I wanted to display that text at x, y and in certain color without specifying its text priority argument
  • Source: Can be used to point to a player if player is not a predefined varible specified in the function. For example playerquit does not have the "player" varible in it. Source is used to point to the player who quit to perform actions on him/her:
on function on PlayerQuit ()
destroyBlipAttachedTo ( source )
  • Converting numbers to strings: A number can be changed to be read as a string by LUA when using it in a string argument of a function. One use for this is with the function textItem = textCreateTextItem ( string text, float x, float y ) - if you wanted to display a score varible (groveteamscore = a number), you would need to convert it to be read as a string by LUA so satisfies the requirement of the function for the text to be a string. You can use the following methods to convert the number varible to a string varible:

1. Use a string (can be empty: "" to not display anything ) and append the number varible to the string using .. so it satisfies the function:

textItem = textCreateTextItem ( "Score: " .. groveteamscore, 0.5, 0.5 )

2. Use the tostring() function which will convert your number to be read as a string of text by LUA

textItem = textCreateTextItem ( "Score: " .. tostring(groveteamscore), 0.5, 0.5 )
  • Converting strings to numbers:: id = tonumber ( gettok ( text, 3, 32 ) )
  • RandInt & RandFloat: + skipping numbers inbetween lower_limit+randint()*upper_limiter

randFloat () * 0.94 + 0.01

  • Doing Math Right - Using Parenthesis:
  • Time Measurement of MS: 1000 = 1 minute
  • Check type -bit here about checking argument type with type()-
  • Tables as strings and [#] and nested tables -bit here-

Refer to string tables as Table.string

Creating a table of varibles.. ex: buyWeaponText = {} --Must declare an empty table to use for filling in values

   for k, v in ipairs(buyWeapon) do
   	buyWeaponText[k] = textCreateTextItem ( "Purchase Price: $"..tostring(buyWeapon[k].buyWeaponPrice), 0.2, 0.3, nil, 0, 170, 0, nil, 3 )         

textDisplayAddText ( buyWeaponDisplay, buyWeaponText[k] )

  • k,v in i(pairs)

(in order pair checking, possible with continuous table (array) vs.(pairs) table with numbering that has holes and pairs must be checked in random out of order)

Triggering a custom function: in another function type "Explosion()" for example to activate function "function Explosion ()". This would activate it once. You could use a timer to trigger how many times it was activated.

  • Using double quotes in a string A backslash before a double quote will stop it from being recognized as the beginning or end of a string. For example: outputChatBox ( " Ransom called Fedor a \"disgrace\" for not being patient enough to learn Lua. " )

Other LUA Tips & Tricks

id - This page is a collection of various IDs (weapons, cars, clothes, sounds, upgrades, weather, skins, etc) Bold text