⚙️ 03 — Native Functions
INFO
Le native sono funzioni C/C++ del motore di GTA V esposte a Lua, C# e JS da FiveM. Ogni interazione col gioco — spostare un giocatore, creare un veicolo, mostrare testo — passa attraverso una native.
| Obiettivo | Dettagli |
|---|---|
| Cosa imparerai | - Usare le native di GTA V per interagire col gioco - Gestire giocatori, veicoli, ped e NPC - Applicare il pattern Request-Then-Use per modelli e animazioni |
| Prerequisiti | Conoscenze base di Lua, completamento file 02 |
Cosa Sono le Native
Le native sono funzioni C/C++ del motore di GTA V esposte a Lua/C#/JS da FiveM. Ogni azione interagisce col gioco tramite native:
- Spostare un giocatore →
SetEntityCoords - Dare un’arma →
GiveWeaponToPed - Creare un veicolo →
CreateVehicle - Mostrare testo a schermo →
BeginTextCommandDisplayText
flowchart LR L[Script Lua] --> N[Chiamata Native] N --> C[Citizen Invoker] C --> G[GTA V Game Engine] G --> R[Resultato] R --> L
Dove Trovare le Native
Documentazione ufficiale: docs.fivem.net/natives/
Ogni native ha una pagina con:
- Nome (es.
GetPlayerPed) - Hash (es.
0x43A66C31C68491C0) - Parametri e tipi
- Valore di ritorno
- Esempi di utilizzo
Convenzioni di Nomenclatura
| Pattern | Esempio | Descrizione |
|---|---|---|
Get | GetEntityCoords | Legge un valore |
Set | SetEntityCoords | Imposta un valore |
Is | IsPlayerOnline | Controlla stato booleano |
Has | HasEntityBeenDamaged | Controlla stato |
Create | CreateVehicle | Crea un’entità |
Delete / Remove | DeleteEntity | Rimuove un’entità |
Task | TaskWanderStandard | Assegna compito a un ped |
Request | RequestModel | Richiede caricamento risorsa |
Hash delle Native
Internamente, FiveM identifica le native con un hash a 64-bit. Puoi usare hash o nome:
-- Per nome (leggibile)
local coords = GetEntityCoords(ped)
-- Per hash (leggermente più veloce)
-- local coords = Citizen.InvokeNative(0x3FEF770D40960D5A, ped)
-- Non serve mai farlo manualmente — il nome è tradotto automaticamenteGestione Giocatore
Ottenere il ped del giocatore
-- client.lua
Citizen.CreateThread(function()
while true do
Citizen.Wait(1000)
local ped = PlayerPedId()
if ped ~= 0 then
local salute = GetEntityHealth(ped)
local armatura = GetPedArmour(ped)
local maxSalute = GetEntityMaxHealth(ped)
print(string.format(
"Ped: %d | HP: %d/%d | Armatura: %d",
ped, salute, maxSalute, armatura
))
end
end
end)Posizione e heading
-- client.lua
RegisterCommand("pos", function()
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)
print(string.format("Posizione: %.2f, %.2f, %.2f", coords.x, coords.y, coords.z))
print(string.format("Heading: %.2f", heading))
-- Copia negli appunti
-- SetClipboard(("{%.6f, %.6f, %.6f}"):format(coords.x, coords.y, coords.z))
end, false)
-- Teletrasporto
RegisterCommand("tp", function(source, args)
local x = tonumber(args[1])
local y = tonumber(args[2])
local z = tonumber(args[3])
if x and y and z then
local ped = PlayerPedId()
SetEntityCoords(ped, x, y, z, false, false, false, false)
print("Teletrasportato a", x, y, z)
else
print("Uso: /tp x y z")
end
end, false)Modellare il giocatore
-- client.lua
RegisterCommand("skin", function(source, args)
local modelName = args[1]
local model = GetHashKey(modelName)
-- Richiedi il modello
RequestModel(model)
-- Aspetta che sia caricato
local timeout = 0
while not HasModelLoaded(model) and timeout < 100 do
Citizen.Wait(10)
timeout = timeout + 1
RequestModel(model)
end
if HasModelLoaded(model) then
SetPlayerModel(PlayerId(), model)
SetModelAsNoLongerNeeded(model)
print("Modello cambiato a", modelName)
else
print("ERRORE: modello", modelName, "non trovato")
end
end, false)Gestione Veicoli
Spawnare un veicolo
-- client.lua
RegisterCommand("veh", function(source, args)
local modello = args[1]
if not modello then
print("Uso: /veh [modello]")
return
end
SpawnaVeicolo(modello)
end, false)
function SpawnaVeicolo(modello)
local hash = GetHashKey(modello)
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)
RequestModel(hash)
local timeout = 0
while not HasModelLoaded(hash) and timeout < 100 do
Citizen.Wait(10)
timeout = timeout + 1
RequestModel(hash)
end
if HasModelLoaded(hash) then
local veicolo = CreateVehicle(hash, coords.x, coords.y, coords.z + 2.0, heading, true, false)
SetPedIntoVehicle(ped, veicolo, -1) -- -1 = posto guida
SetVehicleEngineOn(veicolo, true, true, false)
SetModelAsNoLongerNeeded(hash)
print("Veicolo", modello, "spawnato. ID:", veicolo)
else
print("ERRORE: modello veicolo", modello, "non valido")
end
end
-- pattern RequestModel unificato
function CaricaModello(hash)
RequestModel(hash)
local tentativi = 0
while not HasModelLoaded(hash) and tentativi < 100 do
Citizen.Wait(10)
tentativi = tentativi + 1
if tentativi % 20 == 0 then
RequestModel(hash) -- richiedi di nuovo ogni 200ms
end
end
return HasModelLoaded(hash)
endModificare un veicolo
-- client.lua
RegisterCommand("mod", function(source, args)
local ped = PlayerPedId()
local veicolo = GetVehiclePedIsIn(ped, false)
if veicolo == 0 then
print("Non sei in un veicolo")
return
end
-- Colore primario e secondario
SetVehicleColours(veicolo, 120, 0) -- rosso / nero
-- Colore extra (cerchi, interni)
SetVehicleExtraColours(veicolo, 1, 0)
-- Modifiche prestazioni
SetVehicleModKit(veicolo, 0)
SetVehicleMod(veicolo, 11, 3, false) -- motore livello 3
SetVehicleMod(veicolo, 12, 2, false) -- freni livello 2
SetVehicleMod(veicolo, 13, 1, false) -- trasmissione livello 1
SetVehicleMod(veicolo, 18, 1, false) -- turbo
-- Tuning estetico
SetVehicleMod(veicolo, 0, 1, false) -- paraurti anteriore
SetVehicleMod(veicolo, 1, 1, false) -- paraurti posteriore
SetVehicleMod(veicolo, 2, 2, false) -- minigonne laterali
-- Tinted windows
SetVehicleWindowTint(veicolo, 1) -- 1 = scuro
-- Neon
SetVehicleNeonLightEnabled(veicolo, 0, true)
SetVehicleNeonLightEnabled(veicolo, 1, true)
SetVehicleNeonLightEnabled(veicolo, 2, true)
SetVehicleNeonLightEnabled(veicolo, 3, true)
SetVehicleNeonLightsColour(veicolo, 255, 0, 0) -- rosso
ToggleVehicleMod(veicolo, 22, true) -- pneumatici da drift
print("Veicolo modificato!")
end, false)Gestione Armi
-- client.lua
RegisterCommand("arma", function(source, args)
local ped = PlayerPedId()
local nomeArma = args[1] or "WEAPON_PISTOL"
local munizioni = tonumber(args[2]) or 250
local hash = GetHashKey(nomeArma)
-- Dai l'arma al giocatore
GiveWeaponToPed(ped, hash, munizioni, false, true)
-- Selezionala automaticamente
SetCurrentPedWeapon(ped, hash, true)
print("Arma", nomeArma, "data con", munizioni, "colpi")
-- Per tutte le armi disponibili:
-- WEAPON_PISTOL, WEAPON_ASSAULTRIFLE, WEAPON_CARBINERIFLE,
-- WEAPON_PUMPSHOTGUN, WEAPON_KNIFE, WEAPON_GRENADE, ecc.
end, false)
RegisterCommand("armaop", function()
local ped = PlayerPedId()
local hash = GetHashKey("WEAPON_RAILGUN")
GiveWeaponToPed(ped, hash, 9999, false, true)
SetPedInfiniteAmmo(ped, true, hash)
end, false)Gestione Ped (NPC)
-- client.lua
function SpawnaPed(modello, x, y, z, heading)
local hash = GetHashKey(modello)
if not CaricaModello(hash) then
print("ERRORE: modello", modello, "non caricato")
return nil
end
-- Crea ped come network (true = sincronizzato con server)
local ped = CreatePed(0, hash, x, y, z, heading, true, true)
SetModelAsNoLongerNeeded(hash)
-- Rende il ped immune
SetEntityInvincible(ped, true)
SetPedCanRagdoll(ped, false)
-- Non fugge
SetPedFleeAttributes(ped, 0, true)
-- Animazione di default
TaskStartScenarioInPlace(ped, "WORLD_HUMAN_HANG_OUT_STREET", 0, true)
return ped
end
RegisterCommand("npc", function()
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)
local npc = SpawnaPed(
"a_m_y_beach_01",
coords.x + 3.0, coords.y, coords.z - 1.0,
heading + 180
)
if npc then
print("NPC creato con ID:", npc)
end
end, false)Pattern Comuni
Request-Then-Use Pattern
WARNING
Carica sempre i modelli prima di usarli. Creare un’entità senza
RequestModel+HasModelLoadedcausa crash immediato. Usa un timeout per evitare loop infiniti su modelli mancanti.
Questo pattern si ripete ovunque in FiveM: Richiedi → Aspetta → Usa → Libera.
function CaricaModello(modelHash)
RequestModel(modelHash)
local tentativi = 0
while not HasModelLoaded(modelHash) do
tentativi = tentativi + 1
Citizen.Wait(10)
if tentativi > 500 then -- 5 secondi timeout
return false
end
if tentativi % 25 == 0 then
RequestModel(modelHash)
end
end
return true
end
-- Stesso pattern per animazioni
function CaricaDict(dict)
RequestAnimDict(dict)
local tentativi = 0
while not HasAnimDictLoaded(dict) do
tentativi = tentativi + 1
Citizen.Wait(10)
if tentativi > 500 then return false end
if tentativi % 25 == 0 then
RequestAnimDict(dict)
end
end
return true
end
-- Stesso pattern per texture / streaming
function CaricaTexture(streamedDict)
RequestStreamedTextureDict(streamedDict, false)
local tentativi = 0
while not HasStreamedTextureDictLoaded(streamedDict) do
tentativi = tentativi + 1
Citizen.Wait(10)
if tentativi > 500 then return false end
if tentativi % 25 == 0 then
RequestStreamedTextureDict(streamedDict, false)
end
end
return true
endGiocare un’animazione
TIP
Usa
ClearPedTasks(ped)per fermare qualsiasi animazione in corso. Per animazioni che devono partire sempre da capo, chiamala prima diTaskPlayAnim.
-- client.lua
RegisterCommand("balla", function()
local ped = PlayerPedId()
if CaricaDict("anim@mp_player_intcelebrationmale@air_shuffle") then
TaskPlayAnim(ped, "anim@mp_player_intcelebrationmale@air_shuffle",
"air_shuffle", 8.0, -8.0, -1, 49, 0, false, false, false)
end
end, false)
RegisterCommand("stopanim", function()
local ped = PlayerPedId()
ClearPedTasks(ped)
end, false)Rilevare input giocatore
-- client.lua
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
-- Tasto E premuto?
if IsControlJustPressed(0, 38) then -- 38 = E
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
-- Controlla se vicino a un veicolo
local veicolo = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71)
if veicolo ~= 0 then
print("Vicino a veicolo", veicolo, "— premi E per entrare")
end
-- Controlla se vicino a un ped
local pedTarget = GetClosestPed(coords.x, coords.y, coords.z, 3.0, true, true)
if pedTarget ~= 0 and pedTarget ~= ped then
print("Vicino a NPC", pedTarget)
end
end
end
end)
-- Lista tasti comuni:
-- 38 = E | 51 = E (alternativo)
-- 24 = SPACE | 22 = INVIO
-- 36 = CTRL | 21 = SHIFT
-- 201 = SU | 208 = GIÙ
-- 203 = SINISTRA | 205 = DESTRAText UI (aiuto a schermo)
-- client.lua
function DrawText3D(x, y, z, testo)
local onScreen, _x, _y = World3dToScreen2d(x, y, z)
local scale = 0.35
if onScreen then
SetTextScale(0.0, scale)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry("STRING")
SetTextCentre(true)
AddTextComponentString(testo)
DrawText(_x, _y)
-- Sfondo
local larghezza = string.len(testo) * 0.007
DrawRect(_x, _y + 0.012, larghezza, 0.028, 0, 0, 0, 150)
end
end
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
-- Mostra testo sopra la testa del giocatore
DrawText3D(coords.x, coords.y, coords.z + 1.0, "Giocatore: " .. GetPlayerName(PlayerId()))
end
end)QUESTION
Riflessione: Stai chiamando native in loop che potrebbero essere evitate?
GetEntityCoordsePlayerPedIdsono economiche, ma chiamate comeRequestModelin loop senza controllo possono impattare le performance.
Best Practices
| Regola | Perché |
|---|---|
| Usa sempre RequestModel + HasModelLoaded | Creare un’entità senza caricarla prima = crash |
| Timeout sui caricamenti | Modello mancante = loop infinito |
| SetModelAsNoLongerNeeded dopo l’uso | Libera memoria |
| Controlla che un’entità esista | DoesEntityExist(id) prima di usarla |
| Non chiamare native inutilmente nei loop | Usa Wait(N) più alto quando possibile |
| Preferisci versioni native con nome | Più leggibili, stesso costo |
| Usa i delegati di controllo | IsControlJustPressed per input, non polling su variabili |
TIP
Prossimo passo: 04 - Esport e Import
Torna alla: Indice Generale