>
Tutoriel 2026-03-24

Système de courses pour FiveM

OntelMonke

OntelMonke

Administrateur et développeur chez Agency Scripts

Conception du système de création de course

Un système de course de rue convaincant commence par donner aux joueurs le pouvoir de créer et de gérer leurs propres parcours de course. Plutôt que de s'appuyer uniquement sur des pistes prédéfinies, les meilleurs scripts de course permettent aux organisateurs de placer des points de contrôle de manière dynamique en parcourant un itinéraire et en marquant les positions. Stockez chaque course sous forme de structure de données contenant un identifiant unique, l'identifiant du joueur du créateur, un nom, la liste ordonnée des coordonnées des points de contrôle avec les angles de cap et des métadonnées telles que la distance et le temps au tour estimé. Le processus de création doit être intuitif : le joueur entre dans un mode éditeur de course, se dirige vers chaque point de contrôle, confirme le placement en appuyant sur une touche et termine en revenant à la ligne de départ. Enregistrez les courses terminées dans ton base de données afin qu'elles persistent lors des redémarrages du serveur et puissent être partagées avec la communauté. Implémentez un système de révision dans lequel les administrateurs peuvent approuver les itinéraires créés par les joueurs avant qu'ils n'apparaissent dans la liste publique des courses, évitant ainsi les problèmes liés à des conceptions de pistes impossibles ou injustes.

Système de points de contrôle et logique de course

Les points de contrôle sont le mécanisme de base qui valide la progression de la course et empêche les raccourcis. Chaque point de contrôle doit être défini comme une zone 3D avec un rayon configurable, généralement compris entre 8 et 15 mètres selon la largeur de la route. Utilisez les fonctions de dessin de marqueurs natives de GTA pour afficher visuellement les points de contrôle, le point de contrôle actuel étant mis en surbrillance dans une couleur vive et le suivant affiché sous forme d'aperçu transparent. Suivez la progression de chaque coureur grâce à une liste de points de contrôle indexée, en les faisant avancer uniquement lorsqu'ils entrent dans la zone de point de contrôle suivante correcte dans l'ordre. Mettez en œuvre des mesures anti-triche en suivant le temps entre les points de contrôle et en signalant ou en disqualifiant les coureurs qui terminent des segments à une vitesse incroyablement rapide, ce qui indique une téléportation ou un piratage rapide.

-- Client-side checkpoint detection
local currentCheckpoint = 1
local raceCheckpoints = {} -- populated when race starts

CreateThread(function()
    while isRacing do
        local playerCoords = GetEntityCoords(PlayerPedId())
        local checkpoint = raceCheckpoints[currentCheckpoint]

        if checkpoint then
            local dist = #(playerCoords - checkpoint.coords)

            -- Draw current checkpoint marker
            DrawMarker(1, checkpoint.coords.x, checkpoint.coords.y,
                checkpoint.coords.z - 1.0, 0, 0, 0, 0, 0, 0,
                checkpoint.radius * 2, checkpoint.radius * 2, 2.0,
                45, 212, 191, 120, false, true, 2, false, nil, nil, false)

            if dist < checkpoint.radius then
                PlaySoundFrontend(-1, 'CHECKPOINT_NORMAL', 'HUD_MINI_GAME_SOUNDSET', true)
                currentCheckpoint = currentCheckpoint + 1

                if currentCheckpoint > #raceCheckpoints then
                    -- Race finished
                    local finishTime = GetGameTimer() - raceStartTime
                    TriggerServerEvent('racing:finished', raceId, finishTime)
                    isRacing = false
                else
                    -- Notify server of checkpoint progress
                    TriggerServerEvent('racing:checkpoint', raceId, currentCheckpoint)
                end
            end
        end
        Wait(50)
    end
end)

Classement et système de classement

Les classements stimulent la compétition et incitent les joueurs à revenir pour améliorer leurs temps. Stockez les résultats de la course dans une table de base de données qui enregistre l'identifiant du joueur, l'identifiant de la course, le temps d'achèvement en millisecondes, le modèle de véhicule utilisé, la date et si la course était un record personnel. Affichez les classements via une interface NUI qui affiche les meilleurs temps pour chaque piste, filtrables par classe de véhicule afin que les joueurs puissent comparer équitablement au sein de catégories telles que sport, super, muscle ou compact. Mettez en œuvre un système de classement saisonnier qui se réinitialise périodiquement pour garder la compétition à jour, tout en conservant un tableau des records de tous les temps pour le droit de se vanter historiquement. Calculez un classement de course de style ELO basé sur les performances en face-à-face dans les courses multijoueurs, donnant aux coureurs expérimentés un rang visible qui augmente lorsqu'ils battent des adversaires mieux classés et diminue lorsqu'ils perdent contre des adversaires moins bien classés. Affichez cette note sur l'interface utilisateur de la course et utilisez-la pour le matchmaking facultatif lors de l'organisation de courses aléatoires.

Système de paris et de récompenses

Un système de paris ajoute des enjeux financiers aux courses et intègre la scène des courses à l'économie plus large de ton serveur. Autoriser les organisateurs de courses à fixer des frais d'inscription que tous les participants doivent payer, le pot total étant réparti entre les meilleurs selon une répartition configurable telle que 70-20-10 pour la première, la deuxième et la troisième place. Mettez en œuvre un système de paris avec spectateurs dans lequel les joueurs qui ne participent pas à la course peuvent parier sur le résultat, en choisissant un coureur sur lequel ils financeront leur argent. Utilisez la logique côté serveur exclusivement pour toutes les transactions financières afin d’empêcher toute exploitation. Ajoutez une réduction de 5 à 10 % sur tous les paris pour agir comme un puits d’argent pour ton économie. Pour les événements organisés de plus grande envergure, autorisez les administrateurs à ajouter des cagnottes bonus financées par la trésorerie du serveur. Suivez les statistiques de paris par joueur pour détecter et empêcher les schémas de matchs truqués, comme un coureur perdant systématiquement des courses alors que des paris importants sont placés contre lui.

-- Server-side betting handler
local raceBets = {}

RegisterNetEvent('racing:placeBet')
AddEventHandler('racing:placeBet', function(raceId, targetRacerId, amount)
    local src = source
    if not activeRaces[raceId] then return end
    if activeRaces[raceId].state ~= 'lobby' then
        return notify(src, 'Betting is closed once the race starts.', 'error')
    end

    -- Validate the target racer is in this race
    local racerFound = false
    for _, racer in ipairs(activeRaces[raceId].participants) do
        if racer.src == targetRacerId then racerFound = true break end
    end
    if not racerFound then return end

    -- Check and deduct funds
    local playerMoney = GetPlayerMoney(src)
    if playerMoney < amount or amount < Config.MinBet then
        return notify(src, 'Insufficient funds or below minimum bet.', 'error')
    end

    RemoveMoney(src, amount)

    if not raceBets[raceId] then raceBets[raceId] = {} end
    table.insert(raceBets[raceId], {
        bettor = src,
        target = targetRacerId,
        amount = amount,
    })

    notify(src, ('Bet $%s on %s'):format(amount, GetPlayerName(targetRacerId)), 'success')
end)

Création de l'interface utilisateur de course avec NUI

L’interface utilisateur de course doit transmettre des informations critiques en temps réel sans encombrer l’écran ni distraire le conducteur. Concevez un HUD minimal qui affiche la position actuelle parmi les coureurs, le numéro du tour le cas échéant, un chronomètre intermédiaire comparant la course en cours au record personnel ou au record de piste, et une superposition de mini-carte mettant en évidence la direction du point de contrôle à venir. Utilisez un compteur de vitesse qui correspond au thème de la course, indiquant la vitesse en mph ou en km/h en fonction des préférences du joueur. L'écran du lobby avant une course doit afficher tous les participants inscrits avec leurs véhicules, le nom de la piste et la distance, la répartition de la cagnotte et un compte à rebours. Créez l'interface utilisateur avec HTML, CSS et JavaScript à l'aide du système NUI et communiquez les mises à jour de l'état de course du Lua côté client au cadre NUI via SendNUIMessage. Gardez l'interface utilisateur réactive en limitant les mises à jour de position à 4 à 5 fois par seconde plutôt qu'à chaque image, ce qui réduit considérablement la surcharge du NUI sans aucun impact visible sur les informations affichées. Pensez à ajouter un écran de résultats d'après-course avec des statistiques détaillées telles que la vitesse maximale atteinte, la vitesse moyenne et la comparaison du temps par segment de point de contrôle.

Catégories de course et classes de véhicules

Organisez les courses en catégories distinctes pour garantir une compétition équitable et variée. Définissez des classes de véhicules en fonction de mesures de performances telles que la vitesse de pointe, l'accélération et les notes de maniabilité extraites des données de maniabilité natives du jeu. Créez des restrictions de classe pour des races spécifiques afin qu'un joueur d'un Dominator ne puisse pas participer à une course réservée aux compacts, et vice versa. Au-delà de la catégorie de véhicule, proposez différents formats de course : des sprints point à point qui vont d'un point A à un point B à travers la ville, des courses sur circuit avec plusieurs tours autour d'une boucle, des courses d'accélération sur des routes droites avec des départs avec temps de réaction et des compétitions de drift notées par l'angle, la vitesse et la proximité des points de coupure. Chaque format nécessite une logique légèrement différente pour la détection de notation et d'achèvement. Le score de dérive nécessite notamment un algorithme personnalisé qui évalue l'angle de dérapage du véhicule par rapport à son vecteur vitesse, la vitesse maintenue pendant la dérive et des multiplicateurs de bonus pour enchaîner les dérives consécutives sans perdre le contrôle. Permettez aux organisateurs de courses d'activer des options telles que les mécanismes de rattrapage, la surveillance fantôme des autres coureurs pour éviter des collisions pénibles et les paramètres météorologiques ou d'heure de la journée pour l'atmosphère.

Intégration policière et courses illégales

Les courses de rue devraient être une activité illégale qui crée des interactions organiques avec les forces de l'ordre. Lorsqu'une course commence, générez des plaintes concernant le bruit de la part des PNJ de la zone qui apparaissent sur le système de répartition de la police après un délai configurable, donnant aux coureurs une longueur d'avance mais garantissant que les courses plus longues attirent l'attention. Les policiers qui interviennent peuvent tenter d'arrêter la course en déployant des bandes à crampons, en installant des barrages routiers ou en poursuivant des coureurs individuels. Si un coureur est arrêté par la police, il s'expose à des amendes, à la mise en fourrière du véhicule et potentiellement à une peine de prison, ce qui ajoute de réelles conséquences qui rendent la scène des courses dangereuse et passionnante. Mettez en œuvre un système de niveaux de recherche spécifiquement pour les courses qui s'intensifie avec les récidives, afin que les coureurs de rue chroniques attirent des réponses policières plus agressives au fil du temps. Autoriser la police à utiliser des caméras de surveillance sur des lieux de course connus pour monter des dossiers contre les organisateurs, créant ainsi un niveau d'enquête qui récompense le travail patient de la police avec des arrestations plus importantes qui éliminent des équipes de course entières plutôt que des pilotes individuels.

Optimisation des performances pour la course

Les systèmes de course exigent des performances fluides, car même un décalage mineur peut gâcher l'expérience de compétition. Minimisez la communication serveur-client pendant les courses actives en gérant la détection des points de contrôle et le suivi de position côté client, en envoyant des mises à jour au serveur uniquement lorsqu'un point de contrôle est atteint ou que la course se termine. Utilisez des sacs d'état d'entité pour la diffusion de position au lieu d'événements réseau personnalisés, car les sacs d'état sont optimisés pour des mises à jour fréquentes et gèrent la bande passante plus efficacement. Pour le rendu des points de contrôle, dessinez uniquement des marqueurs pour le point de contrôle actuel et suivant plutôt que pour tous les points de contrôle simultanément, et utilisez la logique LOD (niveau de détail) pour réduire la complexité des marqueurs à de plus grandes distances. Regroupez tes demandes de données de course en récupérant les classements et les listes de courses par opérations par lots plutôt que par des requêtes individuelles, et mettez en cache les résultats côté client avec une durée de vie courte pour réduire la charge de la base de données pendant les heures de pointe de course. Testez ton système avec le nombre maximum prévu de coureurs simultanés, généralement 8 à 16 par course, pour tu assurer que la synchronisation de position et la validation des points de contrôle évoluent correctement sans chutes d'images ni problèmes de désynchronisation.

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.