Lua Guides, tips & tricks
Lua is the most used language in FiveM/RedM. It's extremely beginner friendly which makes it really popular over languages such as C#. Here you'll find some guides on learning lua, writing it and some general tips & tricks to help you write better code!
Guides & useful links
Lua Beginners Guide by Pohka (opens in a new tab)
Project Error's style guide (opens in a new tab)
Lua Start Guide by PacktPublishing (More indepth) (opens in a new tab)
Simple lua logic (opens in a new tab)
Mock FiveM Server (opens in a new tab)
Simple benchmark for LuaGLM 5.4 (FiveM) (opens in a new tab)
Do's and Don'ts
Don't do GetHashKey('WEAPON_PISTOL')
, do WEAPON_PISTOL
instead. GetHashKey('WEAPON_PISTOL')
converts a string into a hash each time the function is called. Using backticks will instead convert the string into hash during compilation, so any checks will have it hashed in the first place.
Don't do GetPlayerPed(-1)
, do PlayerPedId()
instead. PlayerPedId()
directly returns your ped, while GetPlayerPed(-1)
is checking the ped for the local player id.
Don't do GetDistanceBetweenCoords(coords, coords)
or Vdist2(coords, coords)
, do #(coords - coords)
instead. Using language operations is always faster than calling natives. #(coords - othercoords)
compares two vector3s and spits out quick maths.
Don't do insert loop to disable idle camera here, do DisableIdleCamera(bool)
instead. Running a native is much faster then running a loop.
Don't do IsControlJustPressed()
or IsControlJustReleased()
, do RegisterKeyMapping()
instead. This requires less lines and is faster then making loops.
Utilize it with RegisterCommand()
like so:
RegisterCommand('MyCommand', function()
-- do whatever you want the command to do
print("This is my command. Hello World")
end, false)
RegisterKeyMapping('MyCommand', 'Command Label (settings)', 'keyboard', 'F')
-- ref for inputs: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/
-- RegisterCommand() automatically creates a chat suggestion, remove it by doing this:
TriggerEvent('chat:removeSuggestion', '/MyCommand')
-- You can also tell when a key is released like this:
RegisterCommand('+command', function()
print("Key Pressed!")
end, false)
RegisterCommand('-command', function()
print("Key Released!")
end, false)
RegisterKeyMapping('+command', 'Command Label (Settings)', 'keyboard', 'F')
Always remember to remove an animation after you're done using it.
RequestAnimDict('missminuteman_1ig_2')
while not HasAnimDictLoaded('missminuteman_1ig_2') do
Wait(50)
end
TaskPlayAnim(playerPed, 'missminuteman_1ig_2', 'handsup_enter', 8.0, 8.0, -1, 50, 0, false, false, false)
RemoveAnimDict('missminuteman_1ig_2')
Snippets
Here are some useful(?) code snippets you can use.
Disabling NPCs
Disable NPC peds: +set_infinityPopulation 0
Disable NPC vehicles (server side):
CreateThread(function()
SetRoutingBucketPopulationEnabled(0, false)
end)
Format an integer
Ex: 10000 would be 10,000
function formatInt(i)
return tostring(i):reverse():gsub("%d%d%d", "%1,"):reverse():gsub("^,", "")
end
Cleaning a string
function cleanString(x, y)
-- x = string
-- y = true to save whitespace, default false
if y or false then
x = string.gsub(tostring(x), '[^%w%s_]', '') -- Save WS
return x
else
x = string.gsub(tostring(x), '[^%w_]', '') -- Kill WS
return x
end
end
Get a users playtime
local serverCode = "7b6bor" -- Variable just for the example but you should set the server code directly in the URL
RegisterNetEvent("PrintMyPlayTimeInConsole", function()
local _source = source
local fivemId = GetFivemId(GetPlayerIdentifiers(_source))
if fivemId then
PerformHttpRequest("https://lambda.fivem.net/api/ticket/playtimes/%22..serverCode..%22?identifiers[]=%22..fivemId, function(responseCode, resultData)
if responseCode == 200 then
resultData = json.decode(resultData)
print(_source.." has a playtime of "..resultData[1].seconds.." seconds!")
end
end)
else
print("Can't find fivem id of ".._source)
end
end)
function GetFivemId(userIds) -- Probably not the best way
for i = 1, #userIds, 1 do
if string.sub(userIds[i], 1, string.len("fivem:")) == "fivem:" then
return userIds[i]
end
end
return nil
end
Walk injured when damaged
local hurt = false
CreateThread(function()
while true do
Wait(0)
if GetEntityHealth(PlayerPedId()) <= 159 then
setHurt()
elseif hurt and GetEntityHealth(PlayerPedId()) > 160 then
setNotHurt()
end
end
end)
function setHurt()
hurt = true
RequestAnimSet("move_m@injured")
SetPedMovementClipset(PlayerPedId(), "move_m@injured", true)
end
function setNotHurt()
hurt = false
ResetPedMovementClipset(PlayerPedId())
ResetPedWeaponMovementClipset(PlayerPedId())
ResetPedStrafeClipset(PlayerPedId())
end
Snippets are from the Overextended (opens in a new tab) Discord, credits to respective people.