>
Tutoriel 2026-05-23

Système de location de véhicules pour FiveM

OntelMonke

OntelMonke

Développeur chez Agency Scripts

Pourquoi les systèmes de location améliorent le jeu de rôle

Tous les joueurs d'un serveur de jeu de rôle ne possèdent pas de véhicule, en particulier les nouveaux personnages qui débutent. Un système de location de voitures et de vélos comble cette lacune en fournissant un transport temporaire à des tarifs abordables, en créant des opportunités de jeu de rôle naturelles aux comptoirs de location et en donnant aux nouveaux joueurs la liberté d'explorer la carte sans dépendre des transports en commun ou de la marche. Au-delà du transport de base, les systèmes de location prennent en charge les jeux de rôle touristiques dans lesquels les visiteurs louent des décapotables pour des routes panoramiques, des travaux de livraison qui nécessitent des types de véhicules spécifiques et des scénarios d'événements dans lesquels les joueurs ont besoin de véhicules correspondants pour des croisières ou des courses organisées. Le système génère également un flux de revenus passif pour l’économie des serveurs grâce aux frais de location, aux dépôts de garantie et aux pénalités de retour tardif.

Configuration de la flotte et catégories de véhicules

Organisez ton flotte de location en catégories qui répondent aux différents besoins et budgets des joueurs. Les véhicules économiques offrent un moyen de transport de base abordable, les voitures de milieu de gamme offrent plus de confort et de performances, les véhicules haut de gamme répondent aux expériences de luxe et les motos offrent aux joueurs une alternative à deux roues. Chaque catégorie doit proposer plusieurs options de véhicules avec des prix clairs. Incluez les tarifs de location horaires et journaliers afin que les joueurs puissent choisir l'option la plus économique pour leurs besoins. Définissez la flotte dans un tableau de configuration qui spécifie chaque véhicule disponible avec son prix de location, la caution requise, la catégorie et le modèle d'apparition :

Config.RentalLocations = {
    ['airport'] = {
        label = 'LS Airport Car Rental',
        pedModel = 's_f_y_airhostess_01',
        pedCoords = vector4(-1037.34, -2736.82, 20.17, 238.52),
        spawnPoint = vector4(-1029.12, -2728.91, 20.17, 148.76),
        returnZone = vector3(-1035.00, -2730.00, 20.17),
        returnRadius = 10.0,
        categories = {'economy', 'midrange', 'premium', 'motorcycle'},
    },
    ['downtown'] = {
        label = 'Downtown Bike Rental',
        pedModel = 'a_m_y_business_02',
        pedCoords = vector4(-259.68, -892.41, 31.08, 69.24),
        spawnPoint = vector4(-264.30, -888.12, 31.08, 339.87),
        returnZone = vector3(-260.00, -890.00, 31.08),
        returnRadius = 8.0,
        categories = {'motorcycle', 'bicycle'},
    },
}

Config.RentalFleet = {
    economy = {
        {model = 'blista', label = 'Blista', priceHour = 150, priceDay = 800, deposit = 500},
        {model = 'asea', label = 'Asea', priceHour = 120, priceDay = 650, deposit = 400},
        {model = 'stanier', label = 'Stanier', priceHour = 130, priceDay = 700, deposit = 450},
    },
    midrange = {
        {model = 'schafter2', label = 'Schafter', priceHour = 300, priceDay = 1600, deposit = 1000},
        {model = 'oracle', label = 'Oracle', priceHour = 280, priceDay = 1500, deposit = 900},
    },
    premium = {
        {model = 'felon', label = 'Felon GT', priceHour = 600, priceDay = 3200, deposit = 2500},
        {model = 'exemplar', label = 'Exemplar', priceHour = 550, priceDay = 3000, deposit = 2000},
    },
    motorcycle = {
        {model = 'pcj', label = 'PCJ-600', priceHour = 100, priceDay = 500, deposit = 300},
        {model = 'sanchez', label = 'Sanchez', priceHour = 80, priceDay = 400, deposit = 250},
    },
    bicycle = {
        {model = 'cruiser', label = 'Cruiser Bike', priceHour = 30, priceDay = 150, deposit = 50},
        {model = 'tribike', label = 'Tri-Cycles Race', priceHour = 25, priceDay = 120, deposit = 50},
    },
}

Processus de location et interface NUI

L'interaction de location commence lorsqu'un joueur s'approche du PNJ du comptoir de location. À l'aide d'un système cible ou d'un contrôle de proximité, ouvrez un menu NUI qui affiche les catégories de véhicules disponibles avec des options de filtrage. Chaque fiche de véhicule doit indiquer le nom du modèle, un aperçu de l'image si possible, les tarifs horaires et journaliers, la caution requise et l'état de disponibilité. Lorsque le joueur sélectionne un véhicule et confirme la durée de location, le serveur traite la transaction. Le montant total correspond aux frais de location pour la durée sélectionnée plus le dépôt de garantie. La caution est retenue par le système et remboursée lorsque le véhicule est restitué en bon état. Implémentez la confirmation de location en tant qu'événement de serveur qui valide que le joueur dispose de fonds suffisants, vérifie que le véhicule sélectionné est disponible, facture le joueur et fait apparaître le véhicule de location au point d'apparition désigné :

RegisterNetEvent('rental:server:rentVehicle', function(locationId, vehicleModel, duration)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local location = Config.RentalLocations[locationId]
    if not location then return end

    -- Check if player already has an active rental
    if ActiveRentals[Player.PlayerData.citizenid] then
        TriggerClientEvent('QBCore:Notify', src, 'You already have an active rental', 'error')
        return
    end

    -- Find vehicle config
    local vehicleConfig = nil
    for _, category in pairs(Config.RentalFleet) do
        for _, v in ipairs(category) do
            if v.model == vehicleModel then
                vehicleConfig = v
                break
            end
        end
        if vehicleConfig then break end
    end

    if not vehicleConfig then return end

    -- Calculate cost
    local rentalFee = duration == 'day' and vehicleConfig.priceDay or vehicleConfig.priceHour
    local totalCost = rentalFee + vehicleConfig.deposit

    if Player.Functions.GetMoney('bank') < totalCost then
        TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds. Need $' .. totalCost, 'error')
        return
    end

    -- Charge player
    Player.Functions.RemoveMoney('bank', totalCost, 'vehicle-rental')

    -- Generate rental plate
    local plate = 'RNT' .. math.random(10000, 99999)

    -- Store active rental
    ActiveRentals[Player.PlayerData.citizenid] = {
        model = vehicleModel,
        plate = plate,
        deposit = vehicleConfig.deposit,
        rentalFee = rentalFee,
        startTime = os.time(),
        duration = duration,
        expiresAt = os.time() + (duration == 'day' and 86400 or 3600),
        locationId = locationId,
        initialHealth = 1000,
    }

    TriggerClientEvent('rental:client:spawnVehicle', src, vehicleModel, plate, location.spawnPoint)
    TriggerClientEvent('QBCore:Notify', src, 'Vehicle rented! Return before your time expires.', 'success')
end)

Mécanismes de dépôt et de retour pour dommages

Le système de dépôt de garantie crée une responsabilité sur la façon dont les joueurs traitent les véhicules de location. Lorsque le véhicule est restitué, comparez ses valeurs d'état actuelles avec les valeurs initiales enregistrées au moment de la location. Les véhicules GTA ont des valeurs de santé distinctes pour le moteur, la carrosserie et les composants individuels, tu donnant un contrôle granulaire sur l'évaluation des dommages. Calculez le coût de la réparation en fonction des dommages subis et déduisez-le de la caution avant de rembourser le solde. Si les dommages dépassent le montant de la caution, le joueur ne reçoit aucun remboursement et peut se voir facturer des frais supplémentaires. Si le véhicule est restitué en parfait état, la totalité de la caution est remboursée. Ce système encourage une conduite prudente sans punir les rayures mineures qui sont inévitables dans la physique de conduite de GTA :

RegisterNetEvent('rental:server:returnVehicle', function(vehicleNet)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local citizenid = Player.PlayerData.citizenid
    local rental = ActiveRentals[citizenid]
    if not rental then return end

    local vehicle = NetworkGetEntityFromNetworkId(vehicleNet)
    if not DoesEntityExist(vehicle) then return end

    -- Check plate matches
    local plate = GetVehicleNumberPlateText(vehicle)
    if plate:trim() ~= rental.plate then
        TriggerClientEvent('QBCore:Notify', src, 'This is not your rental vehicle', 'error')
        return
    end

    -- Calculate damage
    local bodyHealth = GetVehicleBodyHealth(vehicle)
    local engineHealth = GetVehicleEngineHealth(vehicle)
    local damagePercent = 1.0 - ((bodyHealth + engineHealth) / 2000.0)
    local repairCost = math.floor(rental.deposit * damagePercent)

    -- Calculate late fee
    local lateFee = 0
    if os.time() > rental.expiresAt then
        local overHours = math.ceil((os.time() - rental.expiresAt) / 3600)
        lateFee = overHours * 200
    end

    -- Refund deposit minus costs
    local refund = math.max(0, rental.deposit - repairCost - lateFee)

    if refund > 0 then
        Player.Functions.AddMoney('bank', refund, 'rental-deposit-refund')
    end

    DeleteEntity(vehicle)
    ActiveRentals[citizenid] = nil

    local message = string.format('Vehicle returned. Deposit: $%d | Repairs: $%d | Late fee: $%d | Refund: $%d',
        rental.deposit, repairCost, lateFee, refund)
    TriggerClientEvent('QBCore:Notify', src, message, refund > 0 and 'success' or 'warning')
end)

Système d'expiration et de retour automatique

Les véhicules de location ne doivent pas persister indéfiniment. Mettez en œuvre un système de minuterie qui suit l’expiration de chaque location et prend les mesures en conséquence. Envoyez au joueur une notification trente minutes avant l'expiration, puis une autre dix minutes et un dernier avertissement cinq minutes. À l’expiration de la location, commencez à facturer des frais de retard par minute jusqu’à un seuil maximum. Si le joueur ne restitue pas le véhicule dans le délai de grâce après l'expiration, le véhicule disparaît automatiquement et perd la totalité de la caution. Cela évite que les véhicules de location abandonnés n’encombrent le serveur. Le contrôle d'expiration doit être exécuté côté serveur à intervalles réguliers, en parcourant toutes les locations actives et en prenant les mesures appropriées en fonction du temps restant. Stockez l'identifiant réseau du véhicule afin de pouvoir le supprimer à distance si nécessaire, et gérez le cas où le véhicule a été détruit avant l'expiration de la location en clôturant automatiquement la location avec une confiscation totale de la caution.

Plusieurs emplacements de location

Placez les emplacements de location aux points stratégiques de la carte où le transport temporaire est le plus logique. L’aéroport est un choix évident pour les joueurs qui viennent d’arriver dans la ville. Les emplacements du centre-ville, à proximité des bâtiments gouvernementaux, accueillent les joueurs qui assistent à des procès ou à des réunions d'affaires. Les emplacements de plage proposent des motos et des vélos pour les activités de loisirs le long du littoral. Chaque emplacement peut offrir un sous-ensemble différent de la flotte, l'aéroport proposant une gamme complète allant de l'économique au premium, tandis que les emplacements sur la plage ne stockent que des motos et des vélos. Personnalisez le modèle de PNJ à chaque emplacement pour qu'il corresponde au paramètre. Les locations à l'aéroport utilisent un modèle commercial professionnel, les locations à la plage utilisent un modèle de surfeur occasionnel et les emplacements du centre-ville utilisent un employé adapté. Cette attention aux détails donne à chaque lieu de location l’impression d’être une entreprise distincte plutôt que des copies identiques du même système.

Suivi GPS et antivol

Les véhicules de location doivent avoir un suivi GPS intégré qui permet à la société de location et au joueur de localiser le véhicule à tout moment. Affichez l'emplacement du véhicule de location sur la carte du joueur avec une icône en forme d'icône distincte. Si le véhicule sort d'une limite configurable, envoyez une notification d'avertissement. Mettez en œuvre des mesures antivol qui empêchent les autres joueurs de stocker ou de garer un véhicule de location, garantissant ainsi qu'il reste sous le contrôle du système de location. Lorsqu'un joueur tente de placer un véhicule de location dans son garage personnel, le système doit bloquer l'action avec une notification expliquant que les véhicules de location ne peuvent pas être stockés. Pour les motos et les vélos, ajoutez un verrou virtuel que seul le joueur locataire peut déverrouiller, évitant ainsi les vols occasionnels. Si un véhicule de location est volé, le joueur loueur devrait pouvoir le signaler via une application téléphonique, déclenchant un ping GPS qui l'aide à localiser le véhicule. Suivez le kilométrage total pendant la location pour connaître les suppléments potentiels sur les locations à kilométrage élevé, ajoutant ainsi une autre couche de gestion réaliste de la location de véhicules.

Intégration commerciale et locations appartenant aux joueurs

Pour les serveurs dotés d'un système de propriété d'entreprise, permettez aux joueurs d'acheter et d'exploiter leur propre entreprise de location. Le propriétaire de l'entreprise définit la composition de la flotte en achetant des véhicules à ajouter au pool de location, détermine les prix, embauche des employés pour gérer le comptoir et perçoit les revenus des locations. Les propriétaires d'entreprise doivent disposer d'un tableau de bord de gestion qui affiche les locations actives, les revenus quotidiens, les taux d'utilisation de la flotte et les coûts de maintenance des véhicules qui accumulent des dommages au cours de plusieurs locations. Les employés peuvent gérer les opérations de réception telles que le traitement des locations et des retours, l'inspection des véhicules restitués pour détecter tout dommage et la transmission des litiges au propriétaire. Cette approche axée sur les joueurs transforme le système de location d'un mécanisme de jeu statique en une entreprise dynamique qui reflète l'esprit entrepreneurial des serveurs de jeu de rôle et crée des opportunités d'emploi pour les joueurs qui préfèrent les rôles de service client plutôt que les jeux d'action.

Partager cet article

Prêt à améliorer votre serveur ?

Découvrez nos scripts FiveM premium dans la boutique Agency Scripts ou rejoignez notre communauté Discord pour le support et les mises à jour.