Jeux Tarifs Pro Infrastructure Guides Blog Partenariat À propos

Bibliothèque de scripts FiveM : 20 scripts Lua gratuits prêts à copier

Une collection de scripts FiveM gratuits et commentés, à copier dans votre serveur : téléportation, véhicules, soins, annonces, liste blanche, blips, météo synchronisée, anti-AFK, logs Discord, zones sûres, salaire ESX et QBCore, et plus.

4 min de lecture Mis à jour le 21 octobre 2026

Cette bibliothèque rassemble des scripts FiveM complets, commentés et prêts à l'emploi. Ils fonctionnent sans framework, sauf mention contraire. Chacun tient dans une seule ressource : copiez les fichiers, ajoutez une ligne au server.cfg, redémarrez.

Installer un script de cette page
  1. Créez un dossier dans resources/[scripts]/, par exemple eso-teleport.
  2. Créez dedans les fichiers indiqués (fxmanifest.lua, client.lua, server.lua…) avec le gestionnaire de fichiers du panel ou en SFTP.
  3. Ajoutez ensure eso-teleport à votre server.cfg.
  4. Redémarrez le serveur depuis txAdmin.
Les commandes d'administration

Les commandes marquées « admin » sont déclarées avec RegisterCommand(..., true) : seuls les joueurs qui ont le droit ACE correspondant peuvent les utiliser. Ajoutez par exemple add_ace group.admin command allow et add_principal identifier.fivem:VOTRE_ID group.admin à votre server.cfg (voir le guide server.cfg FiveM).

Le manifeste commun

Tous les scripts de cette page utilisent ce manifeste. Retirez les lignes client_script ou server_script si le script n'a pas de fichier correspondant.

fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

author 'EsoterHost'
version '1.0.0'

shared_script 'config.lua'   -- si le script a un config.lua
client_script 'client.lua'
server_script 'server.lua'

1. Téléportation : /tp et /tpm (admin)

Téléporte à des coordonnées (/tp 215 -810 30) ou au point de passage posé sur la carte (/tpm).

client.lua
local function teleporter(x, y, z)
  local ped = PlayerPedId()
  local entite = IsPedInAnyVehicle(ped, false) and GetVehiclePedIsIn(ped, false) or ped

  DoScreenFadeOut(300)
  while not IsScreenFadedOut() do Wait(0) end

  -- Cherche le sol : on monte la hauteur jusqu'à trouver une position valide
  local sol, zSol = false, z
  for hauteur = 0, 1000, 25 do
    SetEntityCoordsNoOffset(entite, x, y, hauteur + 0.0, false, false, false)
    RequestCollisionAtCoord(x, y, hauteur + 0.0)
    Wait(25)
    sol, zSol = GetGroundZFor_3dCoord(x, y, hauteur + 0.0, false)
    if sol then break end
  end

  SetEntityCoordsNoOffset(entite, x, y, (sol and zSol or z) + 1.0, false, false, false)
  DoScreenFadeIn(300)
end

RegisterCommand('tp', function(_, args)
  local x, y, z = tonumber(args[1]), tonumber(args[2]), tonumber(args[3])
  if not x or not y then
    return TriggerEvent('chat:addMessage', { args = { 'TP', 'Utilisation : /tp x y [z]' } })
  end
  teleporter(x, y, z or 0.0)
end, true)

RegisterCommand('tpm', function()
  local point = GetFirstBlipInfoId(8)            -- 8 = point de passage
  if not DoesBlipExist(point) then
    return TriggerEvent('chat:addMessage', { args = { 'TP', 'Posez un point de passage sur la carte' } })
  end
  local c = GetBlipInfoIdCoord(point)
  teleporter(c.x, c.y, c.z)
end, true)

2. Faire apparaître un véhicule : /car (admin)

/car adder fait apparaître une Adder et installe le joueur au volant. /dv supprime le véhicule actuel.

client.lua
RegisterCommand('car', function(_, args)
  local modele = args[1] or 'adder'
  local hash = joaat(modele)

  if not IsModelInCdimage(hash) or not IsModelAVehicle(hash) then
    return TriggerEvent('chat:addMessage', { args = { 'Véhicule', ('Modèle inconnu : %s'):format(modele) } })
  end

  RequestModel(hash)
  local limite = GetGameTimer() + 5000
  while not HasModelLoaded(hash) and GetGameTimer() < limite do Wait(10) end
  if not HasModelLoaded(hash) then return end

  local ped = PlayerPedId()
  local coords = GetEntityCoords(ped)

  -- Supprime l'ancien véhicule du joueur, s'il est dedans
  local ancien = GetVehiclePedIsIn(ped, false)
  if ancien ~= 0 then DeleteEntity(ancien) end

  local vehicule = CreateVehicle(hash, coords.x, coords.y, coords.z, GetEntityHeading(ped), true, false)
  SetPedIntoVehicle(ped, vehicule, -1)
  SetVehicleNumberPlateText(vehicule, 'ESOTER')
  SetVehicleOnGroundProperly(vehicule)
  SetEntityAsMissionEntity(vehicule, true, true)
  SetModelAsNoLongerNeeded(hash)
end, true)

RegisterCommand('dv', function()
  local ped = PlayerPedId()
  local vehicule = GetVehiclePedIsIn(ped, false)
  if vehicule == 0 then
    -- pas dans un véhicule : on prend celui juste devant
    local avant = GetOffsetFromEntityInWorldCoords(ped, 0.0, 4.0, 0.0)
    vehicule = GetClosestVehicle(avant.x, avant.y, avant.z, 3.0, 0, 70)
  end
  if vehicule ~= 0 then
    SetEntityAsMissionEntity(vehicule, true, true)
    DeleteVehicle(vehicule)
  end
end, true)

3. Réparer et nettoyer : /fix et /clean (admin)

client.lua
local function vehiculeActuel()
  local vehicule = GetVehiclePedIsIn(PlayerPedId(), false)
  if vehicule == 0 then
    TriggerEvent('chat:addMessage', { args = { 'Garage', 'Montez dans un véhicule' } })
  end
  return vehicule
end

RegisterCommand('fix', function()
  local v = vehiculeActuel()
  if v == 0 then return end
  SetVehicleFixed(v)
  SetVehicleDeformationFixed(v)
  SetVehicleEngineHealth(v, 1000.0)
  SetVehicleBodyHealth(v, 1000.0)
  SetVehiclePetrolTankHealth(v, 1000.0)
  SetVehicleUndriveable(v, false)
  SetVehicleEngineOn(v, true, true, false)
end, true)

RegisterCommand('clean', function()
  local v = vehiculeActuel()
  if v == 0 then return end
  SetVehicleDirtLevel(v, 0.0)
  WashDecalsFromVehicle(v, 1.0)
end, true)

4. Soigner et réanimer : /heal et /revive (admin)

client.lua
RegisterCommand('heal', function()
  local ped = PlayerPedId()
  SetEntityHealth(ped, GetEntityMaxHealth(ped))
  SetPedArmour(ped, 100)
  ClearPedBloodDamage(ped)
  ResetPedVisibleDamage(ped)
end, true)

RegisterCommand('revive', function()
  local ped = PlayerPedId()
  local c = GetEntityCoords(ped)
  NetworkResurrectLocalPlayer(c.x, c.y, c.z, GetEntityHeading(ped), true, false)
  SetEntityHealth(PlayerPedId(), GetEntityMaxHealth(PlayerPedId()))
  ClearPedTasksImmediately(PlayerPedId())
end, true)
Avec un framework

ESX, QBCore et Qbox ont leur propre système de mort et de réanimation (esx_ambulancejob, qb-ambulancejob…). Sur ces serveurs, utilisez leurs commandes plutôt que /revive, pour que l'état du personnage reste cohérent.

5. Annonce à tout le serveur : /annonce (admin)

server.lua
RegisterCommand('annonce', function(src, args)
  local message = table.concat(args, ' ')
  if message == '' then return end

  TriggerClientEvent('chat:addMessage', -1, {
    template = '<div style="padding:8px 12px;margin:4px 0;border-radius:6px;background:rgba(220,60,60,.85)"><b>ANNONCE</b> {0}</div>',
    args = { message },
  })
  print(('[annonce] %s : %s'):format(src == 0 and 'Console' or GetPlayerName(src), message))
end, true)

6. Message de bienvenue et nombre de joueurs

server.lua
AddEventHandler('playerJoining', function()
  local src = source
  local nom = GetPlayerName(src)
  local total = #GetPlayers()

  TriggerClientEvent('chat:addMessage', src, {
    color = { 0, 200, 255 },
    args = { 'Bienvenue', ('Salut %s, tu es le joueur n°%d connecté. Bon jeu !'):format(nom, total) },
  })
  TriggerClientEvent('chat:addMessage', -1, {
    color = { 150, 150, 150 },
    args = { 'Serveur', ('%s a rejoint la ville'):format(nom) },
  })
end)

RegisterCommand('joueurs', function(src)
  local total = #GetPlayers()
  local max = GetConvarInt('sv_maxclients', 48)
  local texte = ('%d / %d joueurs connectés'):format(total, max)
  if src == 0 then return print(texte) end
  TriggerClientEvent('chat:addMessage', src, { args = { 'Serveur', texte } })
end, false)

7. Liste blanche (whitelist) par identifiant

Seuls les joueurs dont l'identifiant figure dans la liste peuvent entrer. Les autres voient un message pendant la connexion.

config.lua
Config = {}

Config.Message = "Ce serveur est en liste blanche. Rejoignez notre Discord pour demander l'accès : discord.gg/votre-code"

-- Identifiants autorisés (visibles dans txAdmin, onglet Players)
Config.Autorises = {
  ['license:0123456789abcdef0123456789abcdef01234567'] = true,
  ['discord:123456789012345678'] = true,
  ['fivem:1234567'] = true,
}
server.lua
AddEventHandler('playerConnecting', function(nom, setKickReason, deferrals)
  local src = source
  deferrals.defer()
  Wait(0)
  deferrals.update(('Vérification de la liste blanche pour %s…'):format(nom))

  for _, identifiant in ipairs(GetPlayerIdentifiers(src)) do
    if Config.Autorises[identifiant] then
      return deferrals.done()                      -- accès accordé
    end
  end

  deferrals.done(Config.Message)                   -- accès refusé, avec le message
end)
Une liste blanche en base de données

Pour gérer la liste sans redémarrer, remplacez la table Config.Autorises par une requête : MySQL.scalar.await('SELECT 1 FROM whitelist WHERE identifier = ?', { identifiant }).

8. Blips sur la carte

Affiche des repères sur la carte et la mini-carte. La liste des icônes et des couleurs est sur docs.fivem.net/docs/game-references/blips.

config.lua
Config = {}

Config.Blips = {
  { nom = 'Commissariat', coords = vector3(428.9, -984.5, 30.7), sprite = 60, couleur = 29, taille = 0.9 },
  { nom = 'Hôpital', coords = vector3(298.6, -584.4, 43.3), sprite = 61, couleur = 2, taille = 0.9 },
  { nom = 'Garage central', coords = vector3(215.8, -810.1, 30.7), sprite = 357, couleur = 3, taille = 0.8 },
  { nom = 'Concessionnaire', coords = vector3(-56.8, -1096.6, 26.4), sprite = 326, couleur = 5, taille = 0.8 },
}
client.lua
CreateThread(function()
  for _, b in ipairs(Config.Blips) do
    local blip = AddBlipForCoord(b.coords.x, b.coords.y, b.coords.z)
    SetBlipSprite(blip, b.sprite)
    SetBlipColour(blip, b.couleur)
    SetBlipScale(blip, b.taille)
    SetBlipAsShortRange(blip, true)              -- visible seulement à proximité sur la mini-carte
    BeginTextCommandSetBlipName('STRING')
    AddTextComponentSubstringPlayerName(b.nom)
    EndTextCommandSetBlipName(blip)
  end
end)

9. Météo et heure synchronisées : /meteo et /heure (admin)

Tous les joueurs voient la même météo et la même heure, gérées par le serveur avec un state bag global.

server.lua
GlobalState.meteo = GlobalState.meteo or 'CLEAR'
GlobalState.heure = GlobalState.heure or 12
GlobalState.minute = GlobalState.minute or 0

local METEOS = {
  CLEAR = true, EXTRASUNNY = true, CLOUDS = true, OVERCAST = true, RAIN = true,
  THUNDER = true, FOGGY = true, SMOG = true, CLEARING = true, SNOW = true, XMAS = true,
}

-- L'heure avance d'une minute de jeu toutes les 2 secondes réelles
CreateThread(function()
  while true do
    Wait(2000)
    local m, h = GlobalState.minute + 1, GlobalState.heure
    if m >= 60 then m, h = 0, (h + 1) % 24 end
    GlobalState.minute, GlobalState.heure = m, h
  end
end)

RegisterCommand('meteo', function(src, args)
  local m = (args[1] or ''):upper()
  if not METEOS[m] then
    local msg = 'Météos : CLEAR, EXTRASUNNY, CLOUDS, OVERCAST, RAIN, THUNDER, FOGGY, SMOG, CLEARING, SNOW, XMAS'
    if src == 0 then print(msg) else TriggerClientEvent('chat:addMessage', src, { args = { 'Météo', msg } }) end
    return
  end
  GlobalState.meteo = m
end, true)

RegisterCommand('heure', function(_, args)
  local h, m = tonumber(args[1]), tonumber(args[2] or 0)
  if h and h >= 0 and h < 24 then GlobalState.heure, GlobalState.minute = h, m or 0 end
end, true)
client.lua
local meteoActuelle = nil

CreateThread(function()
  while true do
    local cible = GlobalState.meteo or 'CLEAR'
    if cible ~= meteoActuelle then
      SetWeatherTypeOverTime(cible, 15.0)        -- transition de 15 secondes
      Wait(15000)
      meteoActuelle = cible
    end
    ClearOverrideWeather()
    ClearWeatherTypePersist()
    SetWeatherTypePersist(meteoActuelle)
    SetWeatherTypeNow(meteoActuelle)
    SetWeatherTypeNowPersist(meteoActuelle)
    SetForceVehicleTrails(meteoActuelle == 'XMAS')
    SetForcePedFootstepsTracks(meteoActuelle == 'XMAS')

    NetworkOverrideClockTime(GlobalState.heure or 12, GlobalState.minute or 0, 0)
    Wait(1000)
  end
end)

10. Messages automatiques

Diffuse un message différent à intervalle régulier : règlement, Discord, boutique.

server.lua
local MESSAGES = {
  "Rejoignez notre Discord : discord.gg/votre-code",
  "Lisez le règlement avant de jouer : /regles",
  "Un problème ? Utilisez /report pour contacter l'équipe",
}
local INTERVALLE_MINUTES = 10

CreateThread(function()
  local i = 1
  while true do
    Wait(INTERVALLE_MINUTES * 60 * 1000)
    TriggerClientEvent('chat:addMessage', -1, { color = { 255, 200, 0 }, args = { 'Info', MESSAGES[i] } })
    i = i % #MESSAGES + 1
  end
end)

11. Expulsion des joueurs inactifs (anti-AFK)

Un joueur qui ne bouge pas pendant 15 minutes est expulsé, après deux avertissements. Les administrateurs sont épargnés.

client.lua
local LIMITE = 15 * 60                    -- secondes
local AVERTISSEMENTS = { 120, 60 }        -- secondes restantes au moment d'avertir
local derniereAction = GetGameTimer()
local dernierePosition = vector3(0, 0, 0)
local averti = {}

CreateThread(function()
  while true do
    Wait(5000)
    local pos = GetEntityCoords(PlayerPedId())
    if #(pos - dernierePosition) > 1.0 then
      derniereAction = GetGameTimer()
      dernierePosition = pos
      averti = {}
    end

    local restant = LIMITE - (GetGameTimer() - derniereAction) // 1000
    if restant <= 0 then
      TriggerServerEvent('eso-afk:expulser')
    else
      for _, seuil in ipairs(AVERTISSEMENTS) do
        if restant <= seuil and not averti[seuil] then
          averti[seuil] = true
          TriggerEvent('chat:addMessage', { color = { 255, 120, 0 }, args = { 'AFK', ('Bougez, sinon vous serez expulsé dans %d secondes'):format(restant) } })
        end
      end
    end
  end
end)
server.lua
RegisterNetEvent('eso-afk:expulser', function()
  local src = source
  if IsPlayerAceAllowed(src, 'afk.ignorer') then return end
  DropPlayer(src, 'Expulsé pour inactivité. Vous pouvez vous reconnecter.')
end)

Pour épargner un groupe : add_ace group.admin afk.ignorer allow dans le server.cfg.

12. Journal des connexions sur Discord

Envoie un message dans un salon Discord à chaque arrivée et départ, avec les identifiants du joueur. Créez un webhook dans les paramètres du salon Discord (Intégrations, Webhooks), puis ajoutez au server.cfg :

server.cfg
set eso_logs_webhook "https://discord.com/api/webhooks/xxxx/yyyy"
server.lua
local WEBHOOK = GetConvar('eso_logs_webhook', '')

local function envoyer(titre, description, couleur)
  if WEBHOOK == '' then return end
  PerformHttpRequest(WEBHOOK, function() end, 'POST', json.encode({
    username = 'Journal du serveur',
    embeds = { {
      title = titre,
      description = description,
      color = couleur,
      timestamp = os.date('!%Y-%m-%dT%H:%M:%SZ'),
    } },
  }), { ['Content-Type'] = 'application/json' })
end

local function identifiants(src)
  local lignes = {}
  for _, id in ipairs(GetPlayerIdentifiers(src)) do
    if not id:find('^ip:') then lignes[#lignes + 1] = '`' .. id .. '`' end   -- l'adresse IP n'est pas publiée
  end
  return table.concat(lignes, '\n')
end

AddEventHandler('playerJoining', function()
  local src = source
  envoyer('Connexion', ('**%s**\n%s'):format(GetPlayerName(src), identifiants(src)), 3066993)
end)

AddEventHandler('playerDropped', function(raison)
  local src = source
  envoyer('Déconnexion', ('**%s**\nRaison : %s'):format(GetPlayerName(src), raison), 15158332)
end)

13. Texte au-dessus du joueur : /me

Affiche une action au-dessus de la tête du joueur pendant 6 secondes, visible par les joueurs proches. Très utilisé en roleplay.

server.lua
RegisterCommand('me', function(src, args)
  local texte = table.concat(args, ' ')
  if src == 0 or texte == '' or #texte > 120 then return end
  TriggerClientEvent('eso-me:afficher', -1, src, texte)
end, false)
client.lua
local actifs = {}

local function dessinerTexte3D(coords, texte)
  local visible, x, y = World3dToScreen2d(coords.x, coords.y, coords.z)
  if not visible then return end
  SetTextScale(0.35, 0.35)
  SetTextFont(4)
  SetTextColour(220, 180, 255, 230)
  SetTextCentre(true)
  SetTextOutline()
  BeginTextCommandDisplayText('STRING')
  AddTextComponentSubstringPlayerName(texte)
  EndTextCommandDisplayText(x, y)
end

RegisterNetEvent('eso-me:afficher', function(serverId, texte)
  local joueur = GetPlayerFromServerId(serverId)
  if joueur == -1 then return end                -- joueur trop loin, pas chargé chez nous
  local ped = GetPlayerPed(joueur)
  if #(GetEntityCoords(ped) - GetEntityCoords(PlayerPedId())) > 25.0 then return end

  local id = {}
  actifs[id] = true
  local fin = GetGameTimer() + 6000
  CreateThread(function()
    while GetGameTimer() < fin and actifs[id] do
      dessinerTexte3D(GetEntityCoords(ped) + vector3(0.0, 0.0, 1.0), '* ' .. texte .. ' *')
      Wait(0)
    end
    actifs[id] = nil
  end)
end)

14. Signalement aux administrateurs : /report

Le joueur envoie un message, les administrateurs connectés le reçoivent (avec l'identifiant du joueur pour répondre).

server.lua
local derniers = {}

RegisterCommand('report', function(src, args)
  if src == 0 then return end
  local message = table.concat(args, ' ')
  if message == '' then
    return TriggerClientEvent('chat:addMessage', src, { args = { 'Report', 'Utilisation : /report votre message' } })
  end
  if derniers[src] and os.time() - derniers[src] < 60 then
    return TriggerClientEvent('chat:addMessage', src, { args = { 'Report', 'Patientez une minute entre deux signalements' } })
  end
  derniers[src] = os.time()

  local recus = 0
  for _, id in ipairs(GetPlayers()) do
    if IsPlayerAceAllowed(id, 'report.recevoir') then
      TriggerClientEvent('chat:addMessage', id, {
        color = { 255, 80, 80 },
        args = { ('Report de %s [%s]'):format(GetPlayerName(src), src), message },
      })
      recus = recus + 1
    end
  end
  TriggerClientEvent('chat:addMessage', src, {
    args = { 'Report', recus > 0 and 'Message transmis à l\'équipe' or 'Aucun membre de l\'équipe connecté, réessayez plus tard' },
  })
end, false)

AddEventHandler('playerDropped', function() derniers[source] = nil end)

Donnez le droit de recevoir les signalements : add_ace group.admin report.recevoir allow.

15. Zones sûres

Dans une zone sûre, les armes sont rangées et les joueurs ne peuvent ni tirer ni se battre.

config.lua
Config = {}

Config.Zones = {
  { nom = 'Hôpital', centre = vector3(298.6, -584.4, 43.3), rayon = 40.0 },
  { nom = 'Commissariat', centre = vector3(428.9, -984.5, 30.7), rayon = 35.0 },
}
client.lua
local dansZone = nil

CreateThread(function()
  while true do
    local pos = GetEntityCoords(PlayerPedId())
    local trouvee = nil
    for _, z in ipairs(Config.Zones) do
      if #(pos - z.centre) < z.rayon then trouvee = z break end
    end
    if trouvee ~= dansZone then
      dansZone = trouvee
      local texte = trouvee and ('Zone sûre : %s'):format(trouvee.nom) or 'Vous quittez la zone sûre'
      BeginTextCommandThefeedPost('STRING')
      AddTextComponentSubstringPlayerName(texte)
      EndTextCommandThefeedPostTicker(false, true)
    end
    Wait(500)
  end
end)

CreateThread(function()
  while true do
    if dansZone then
      local ped = PlayerPedId()
      SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
      DisablePlayerFiring(PlayerId(), true)
      DisableControlAction(0, 24, true)    -- attaque
      DisableControlAction(0, 25, true)    -- viser
      DisableControlAction(0, 140, true)   -- coup léger
      DisableControlAction(0, 141, true)   -- coup fort
      DisableControlAction(0, 142, true)   -- coup alternatif
      Wait(0)
    else
      Wait(500)
    end
  end
end)

16. Sauvegarde de la dernière position (sans framework)

À la reconnexion, le joueur réapparaît là où il s'était déconnecté. Nécessite oxmysql.

table.sql
CREATE TABLE IF NOT EXISTS eso_positions (
  identifier VARCHAR(64) PRIMARY KEY,
  x FLOAT NOT NULL, y FLOAT NOT NULL, z FLOAT NOT NULL, h FLOAT NOT NULL
);
fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

dependency 'oxmysql'
client_script 'client.lua'
server_scripts { '@oxmysql/lib/MySQL.lua', 'server.lua' }
server.lua
local function license(src) return GetPlayerIdentifierByType(src, 'license') end

AddEventHandler('playerDropped', function()
  local src = source
  local id = license(src)
  local ped = GetPlayerPed(src)
  if not id or ped == 0 then return end
  local c = GetEntityCoords(ped)
  if #c < 1.0 then return end                       -- position inconnue, on n'enregistre pas
  MySQL.insert('REPLACE INTO eso_positions (identifier, x, y, z, h) VALUES (?, ?, ?, ?, ?)',
    { id, c.x, c.y, c.z, GetEntityHeading(ped) })
end)

RegisterNetEvent('eso-position:demander', function()
  local src = source
  local row = MySQL.single.await('SELECT x, y, z, h FROM eso_positions WHERE identifier = ?', { license(src) })
  if row then TriggerClientEvent('eso-position:placer', src, row) end
end)
client.lua
AddEventHandler('playerSpawned', function()
  TriggerServerEvent('eso-position:demander')
end)

RegisterNetEvent('eso-position:placer', function(p)
  SetEntityCoordsNoOffset(PlayerPedId(), p.x, p.y, p.z, false, false, false)
  SetEntityHeading(PlayerPedId(), p.h)
end)
Avec un framework

ESX, QBCore et Qbox enregistrent déjà la position du personnage. N'installez ce script que sur un serveur sans framework.

17. Salaire automatique (ESX Legacy et QBCore)

Verse un salaire à chaque joueur connecté toutes les 15 minutes, selon son métier. Les deux frameworks ont déjà un système de paie : ce script montre comment en écrire un sur mesure (bonus de présence, primes de week-end…).

server.lua (ESX Legacy)
local ESX = exports['es_extended']:getSharedObject()
local INTERVALLE = 15 * 60 * 1000
local BONUS_PRESENCE = 50          -- versé à tous, même sans emploi

CreateThread(function()
  while true do
    Wait(INTERVALLE)
    for _, xPlayer in pairs(ESX.GetExtendedPlayers()) do
      local salaire = (xPlayer.job.grade_salary or 0) + BONUS_PRESENCE
      if salaire > 0 then
        xPlayer.addAccountMoney('bank', salaire, 'Salaire')
        xPlayer.showNotification(('Salaire versé : %d $'):format(salaire))
      end
    end
  end
end)
server.lua (QBCore)
local QBCore = exports['qb-core']:GetCoreObject()
local INTERVALLE = 15 * 60 * 1000
local BONUS_PRESENCE = 50

CreateThread(function()
  while true do
    Wait(INTERVALLE)
    for _, Player in pairs(QBCore.Functions.GetQBPlayers()) do
      local job = Player.PlayerData.job
      local paie = (job.onduty and job.payment or 0) + BONUS_PRESENCE
      if paie > 0 then
        Player.Functions.AddMoney('bank', paie, 'salaire')
        TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, ('Salaire versé : %d $'):format(paie), 'success')
      end
    end
  end
end)

18. Moins de PNJ et de circulation

Allège la ville : utile pour les gros serveurs roleplay et pour les performances.

config.lua
Config = {}
Config.Pietons = 0.5          -- 0.0 = aucun, 1.0 = normal
Config.Circulation = 0.4
Config.Stationnes = 0.4
Config.SansPolice = true      -- pas de police ni de recherche par l'IA
client.lua
CreateThread(function()
  while true do
    SetPedDensityMultiplierThisFrame(Config.Pietons)
    SetScenarioPedDensityMultiplierThisFrame(Config.Pietons, Config.Pietons)
    SetVehicleDensityMultiplierThisFrame(Config.Circulation)
    SetRandomVehicleDensityMultiplierThisFrame(Config.Circulation)
    SetParkedVehicleDensityMultiplierThisFrame(Config.Stationnes)
    Wait(0)
  end
end)

CreateThread(function()
  if not Config.SansPolice then return end
  while true do
    local joueur = PlayerId()
    if GetPlayerWantedLevel(joueur) > 0 then
      SetPlayerWantedLevel(joueur, 0, false)
      SetPlayerWantedLevelNow(joueur, false)
    end
    SetMaxWantedLevel(0)
    for i = 1, 15 do EnableDispatchService(i, false) end
    Wait(1000)
  end
end)

19. Compteur de vitesse simple

Affiche la vitesse en km/h en bas de l'écran quand le joueur conduit.

client.lua
local vehicule = 0

CreateThread(function()
  while true do
    vehicule = GetVehiclePedIsIn(PlayerPedId(), false)
    Wait(500)
  end
end)

CreateThread(function()
  while true do
    if vehicule ~= 0 and GetPedInVehicleSeat(vehicule, -1) == PlayerPedId() then
      local kmh = math.floor(GetEntitySpeed(vehicule) * 3.6)
      SetTextFont(4)
      SetTextScale(0.6, 0.6)
      SetTextColour(255, 255, 255, 220)
      SetTextOutline()
      BeginTextCommandDisplayText('STRING')
      AddTextComponentSubstringPlayerName(('%d km/h'):format(kmh))
      EndTextCommandDisplayText(0.16, 0.92)
      Wait(0)
    else
      Wait(500)
    end
  end
end)

20. Commande /id et liste des joueurs proches

client.lua
RegisterCommand('id', function()
  local monId = GetPlayerServerId(PlayerId())
  local proches = {}
  local maPos = GetEntityCoords(PlayerPedId())

  for _, joueur in ipairs(GetActivePlayers()) do
    if joueur ~= PlayerId() then
      local d = #(GetEntityCoords(GetPlayerPed(joueur)) - maPos)
      if d < 30.0 then
        proches[#proches + 1] = ('%s [%d]'):format(GetPlayerName(joueur), GetPlayerServerId(joueur))
      end
    end
  end

  TriggerEvent('chat:addMessage', { args = { 'ID', ('Votre ID : %d'):format(monId) } })
  if #proches > 0 then
    TriggerEvent('chat:addMessage', { args = { 'Proches', table.concat(proches, ', ') } })
  end
end, false)

Aller plus loin

Ces scripts sont libres : modifiez-les, combinez-les, utilisez-les sur votre serveur.


EsoterHost n'est ni approuvé, ni sponsorisé, ni affilié à Rockstar Games ou à Cfx.re. FiveM et Grand Theft Auto V sont des marques de leurs propriétaires.

Ce guide vous a-t-il aidé ? Une question ? Ouvrez un ticket

Vous ne trouvez pas votre réponse ?

Notre équipe répond à vos tickets 7j/7, directement depuis votre espace client.