O que você precisa saber antes
- FiveM usa uma Lua 5.4 modificada (CfxLua) — arquivos com extensão
.lua - Servidor FiveM já rodando (FXServer) com pasta resources
- Editor de texto (VS Code recomendado)
- Base estável ajuda, mas este guia funciona mesmo sem QBCore — se ainda não tem servidor, veja Windows + QBCore
O que é um resource
Um resource é uma pasta com arquivos que o servidor pode start, stop e restart individualmente. Cada script personalizado costuma ser um resource próprio.
Estrutura recomendada para iniciantes:
resources/[local]/meu_primeiro_script/
fxmanifest.lua
client.lua
server.lua
shared/config.lua (opcional) Pastas entre colchetes como [local] só organizam; o nome do resource é a pasta interna (meu_primeiro_script).
1. Criar o fxmanifest.lua
Sem o manifest o FiveM não detecta o resource. Exemplo mínimo (standalone, não é gametype):
fx_version 'cerulean'
game 'gta5'
author 'Seu Nome'
description 'Meu primeiro script em Lua'
version '1.0.0'
shared_script 'shared/config.lua'
client_script 'client.lua'
server_script 'server.lua'- fx_version — use uma versão atual (ex.:
cerulean) para recursos novos - game 'gta5' — indica GTA V / FiveM
- client_script / server_script — o que cada lado carrega
Client × server (regra de ouro)
- Client: teclas, markers, animação, natives de jogo (posição do ped, criar veículo localmente para teste, UI)
- Server: dinheiro, itens, permissões, banco de dados, o que precisa ser a “fonte da verdade”
Cada jogador roda uma cópia do client no PC dele. Variáveis do client não são compartilhadas entre players. Para ações entre jogadores ou recompensas, use o server + eventos.
2. Exemplo prático: comando /ola
No client.lua:
RegisterCommand('ola', function()
TriggerEvent('chat:addMessage', {
args = { 'DEVELOPERWHS', 'Olá! Seu primeiro script Lua está rodando.' }
})
end, false)
-- Sugestão no chat ao digitar /
TriggerEvent('chat:addSuggestion', '/ola', 'Mostra uma mensagem de boas-vindas')No console do FXServer:
refresh
ensure meu_primeiro_script Entre no servidor, abra o chat (T) e digite /ola. Depois de editar o código, use restart meu_primeiro_script — não precisa fechar o jogo.
3. Exemplo prático: /coords (útil no dia a dia)
Script client simples para copiar coordenadas ao montar markers, spawns e pontos de job:
RegisterCommand('coords', function()
local ped = PlayerPedId()
local coordenadas = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)
print(('vector4(%.2f, %.2f, %.2f, %.2f)'):format(
coordenadas.x,
coordenadas.y,
coordenadas.z,
heading
))
TriggerEvent('chat:addMessage', {
args = {
'Coords',
('X: %.2f | Y: %.2f | Z: %.2f | H: %.2f'):format(
coordenadas.x,
coordenadas.y,
coordenadas.z,
heading
)
}
})
end, false) Aqui entram dois conceitos da runtime Lua : vectors (posição com .x, .y, .z) e natives como PlayerPedId e GetEntityCoords.
4. Exemplo: client + server com evento
O jogador pede algo no client; o server decide se aceita. Padrão essencial para qualquer script de emprego ou recompensa.
client.lua — tecla E perto de um ponto:
local pontoEntrega = vector3(215.76, -810.12, 30.73)
local distanciaMaxima = 2.0
CreateThread(function()
while true do
local espera = 1000
local ped = PlayerPedId()
local coordenadas = GetEntityCoords(ped)
local distancia = #(coordenadas - pontoEntrega)
if distancia < 10.0 then
espera = 0
DrawMarker(
2,
pontoEntrega.x, pontoEntrega.y, pontoEntrega.z,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.3, 0.3, 0.3,
56, 189, 248, 180,
false, true, 2, false, nil, nil, false
)
if distancia < distanciaMaxima then
BeginTextCommandDisplayHelp('STRING')
AddTextComponentSubstringPlayerName('Pressione ~INPUT_CONTEXT~ para entregar')
EndTextCommandDisplayHelp(0, false, true, -1)
if IsControlJustReleased(0, 38) then -- E
TriggerServerEvent('meu_primeiro_script:entregar')
end
end
end
Wait(espera)
end
end)server.lua — valida distância e dá a recompensa no server:
local pontoEntrega = vector3(215.76, -810.12, 30.73)
RegisterNetEvent('meu_primeiro_script:entregar', function()
local sourceId = source
local ped = GetPlayerPed(sourceId)
local coordenadas = GetEntityCoords(ped)
local distancia = #(coordenadas - pontoEntrega)
if distancia > 5.0 then
print(('[meu_primeiro_script] jogador %s longe demais'):format(sourceId))
return
end
-- Aqui entraria dinheiro/item via QBCore, ox_inventory, etc.
TriggerClientEvent('chat:addMessage', sourceId, {
args = { 'Entrega', 'Entrega concluída! (+exemplo)' }
})
end) Note o Wait(espera) dinâmico: longe do ponto o loop dorme 1s; perto usa 0 só enquanto precisa desenhar o marker. Isso reduz lag.
5. Hashes com crase (backtick)
Em CfxLua você pode gerar hash em tempo de compilação com `nome` — zero custo em runtime (documentado em Scripting in Lua ):
RequestModel(`adder`)
if GetEntityModel(veiculo) == `buzzard` then
print('É um Buzzard.')
end6. Exports (um resource falando com outro)
Defina um export no seu script e chame de outro resource:
-- no seu resource
exports('DizerOla', function(nome)
print('Olá, ' .. tostring(nome) .. '!')
end)
-- em outro resource
exports.meu_primeiro_script:DizerOla('mundo')No QBCore, a maior parte da integração (player, money, job) passa por exports e callbacks do framework — não reinventar inventário do zero.
Checklist rápido ao criar um script
- Pasta +
fxmanifest.lua refresh+ensure nome_do_resource- Comando ou marker funciona no client
- Ação sensível (dinheiro/item) validada no server
- Nome de eventos com prefixo do resource (evita conflito)
resmon 1sem idle absurdo
Segurança e performance
- Nunca confie em preço, quantidade ou job enviados só pelo client
- Valide distância e permissão no server antes de pagar/dar item
- Evite
Wait(0)o tempo todo sem necessidade - Prefira loops com espera maior quando o jogador está longe
- Não exponha eventos de admin sem ACE / permissão
Próximos passos
Com o básico de resource, comando, evento e export, você já consegue prototipar jobs simples. Para aprofundar: natives, NUI (HTML/CSS/JS) e State Bags na documentação Cfx.re .
Se a base ainda não está organizada, veja como criar uma base QBCore . Fundamentos da linguagem: como programar em Lua . Mais tutoriais no blog — e scripts prontos em WH Emotes , Phone e Smugglers .