Wróć do bloga
Tutorial10 min czytania

System mechanika FiveM: Tuning, naprawa i prace pojazdowe

Stwórz kompletny system mechanika w FiveM. Naprawa, tuning, odholowywanie na parking policyjny, UI warsztatu i najlepsze skrypty mechanika dla serwerów QBCore i ESX.

Agency Scripts

Założyciel i główny deweloper w Agency Scripts

Projektowanie architektury pracy mechanika

System pracy mechanika to jedna z najpopularniejszych i najbardziej satysfakcjonujących funkcji do stworzenia na serwer roleplay FiveM. W przeciwieństwie do prostych skryptów naprawy, które jedynie wywołują SetVehicleFixed(), odpowiedni system mechaników wprowadza kompletną ekonomię pracy ze specjalistycznymi rolami, ekwipunkiem części i interakcjami między graczami, które napędzają roleplay. Architektura musi uwzględniać wiele warsztatów na mapie, z których każdy może należeć do innej grupy graczy, wraz z hierarchią stopni pracy określającą, kto może wykonywać określone naprawy. U podstaw potrzebujesz wspólnej konfiguracji, która definiuje lokalizacje warsztatów, usługi dostępne na poszczególnych poziomach, ceny części oraz stopnie pracy wymagane do odblokowania zaawansowanych napraw, takich jak wymiana silnika czy montaż turbosprężarki. System powinien integrować się z istniejącym frameworkiem prac na Twoim serwerze, niezależnie od tego, czy jest to QBCore, ESX czy rozwiązanie niestandardowe, aby gracze mogli rozpoczynać i kończyć służbę mechanika z prawidłową obsługą wypłat i śledzeniem statusu służby.

Rangi prac i system uprawnień

Wielopoziomowy system stopni zawodowych nadaje pracy mechanika głębi i motywuje graczy do wspinania się po szczeblach kariery. Zacznij od zdefiniowania jasnych stopni z określonymi uprawnieniami: stażysta może jedynie myć pojazdy i naprawiać drobne uszkodzenia karoserii, zwykły mechanik poradzi sobie z naprawami silnika i wymianą opon, starszy mechanik odblokowuje tuning osiągów i lakierowanie, a właściciel warsztatu może zarządzać pracownikami i ustalać cennik usług. Zapisz te definicje stopni we wspólnym configu, aby zarówno klient, jak i serwer mogły się do nich spójnie odwoływać. Oto przykładowa konfiguracja mapująca stopnie na dozwolone usługi:

Config.MechanicGrades = {
    [0] = {
        label = 'Trainee',
        services = {'wash', 'body_minor'},
        payMultiplier = 0.7
    },
    [1] = {
        label = 'Mechanic',
        services = {'wash', 'body_minor', 'body_major', 'engine_repair', 'tire_replace', 'brake_repair'},
        payMultiplier = 1.0
    },
    [2] = {
        label = 'Senior Mechanic',
        services = {'wash', 'body_minor', 'body_major', 'engine_repair', 'tire_replace',
                    'brake_repair', 'spray_paint', 'performance_tune', 'turbo_install'},
        payMultiplier = 1.3
    },
    [3] = {
        label = 'Shop Owner',
        services = 'all',
        payMultiplier = 1.5,
        canManage = true
    }
}

Config.ServicePrices = {
    wash = 200,
    body_minor = 800,
    body_major = 2500,
    engine_repair = 3500,
    tire_replace = 1200,
    brake_repair = 1500,
    spray_paint = 5000,
    performance_tune = 15000,
    turbo_install = 25000
}

Po stronie serwera zawsze weryfikuj stopień gracza przed zezwoleniem na wykonanie jakiejkolwiek usługi. Nigdy nie ufaj klientowi w kwestii dostępnych usług, ponieważ cheater mógłby zmodyfikować NUI, aby wysłać dowolne żądanie usługi. Callback serwera powinien sprawdzić aktualną pracę gracza, jego stopień oraz to, czy żądana usługa znajduje się na liście usług dla jego rangi, zanim przejdzie do naprawy.

Mechanika naprawy pojazdów i system części

Realistyczna mechanika naprawy wykracza poza pojedyncze wywołanie natywne. Zamiast natychmiast naprawiać pojazd, podziel proces naprawy na etapy, które wymagają czasu i zużywają części z ekwipunku mechanika. Gdy gracz przyprowadza samochód do naprawy silnika, mechanik powinien potrzebować odpowiednich części w swoim osobistym ekwipunku lub we wspólnym schowku warsztatu. Użyj systemu pasków postępu, aby symulować czas trwania naprawy, co tworzy naturalne momenty roleplay, w których klient czeka i wchodzi w interakcję z mechanikiem. Logika naprawy powinna celować w konkretne komponenty pojazdu za pomocą funkcji natywnych, aby można było naprawić silnik bez naprawiania uszkodzeń karoserii lub wymienić opony bez wpływu na stan silnika:

local RepairFunctions = {
    engine_repair = function(vehicle)
        local parts = {'engine_oil', 'spark_plugs', 'coolant'}
        if not HasRequiredParts(parts) then
            return false, 'Missing required parts'
        end

        RemovePartsFromInventory(parts)

        -- Animate the repair
        TaskTurnPedToFaceEntity(PlayerPedId(), vehicle, 1000)
        Wait(1000)

        if not StartProgressBar('Repairing engine...', 15000, 'mechanic_repair') then
            return false, 'Repair cancelled'
        end

        SetVehicleEngineHealth(vehicle, 1000.0)
        SetVehicleEngineOn(vehicle, true, true, false)
        return true
    end,

    body_major = function(vehicle)
        local parts = {'body_panel', 'filler_putty', 'paint_primer'}
        if not HasRequiredParts(parts) then
            return false, 'Missing required parts'
        end

        RemovePartsFromInventory(parts)

        if not StartProgressBar('Repairing body damage...', 20000, 'mechanic_repair') then
            return false, 'Repair cancelled'
        end

        SetVehicleBodyHealth(vehicle, 1000.0)
        SetVehicleDeformationFixed(vehicle)
        return true
    end,

    tire_replace = function(vehicle, tireIndex)
        local parts = {'tire_set'}
        if not HasRequiredParts(parts) then
            return false, 'Missing required parts'
        end

        RemovePartsFromInventory(parts)

        if not StartProgressBar('Replacing tire...', 8000, 'mechanic_repair') then
            return false, 'Repair cancelled'
        end

        SetVehicleTyreFixed(vehicle, tireIndex)
        return true
    end
}

System części tworzy dodatkową warstwę ekonomii na twoim serwerze. Umieszczaj części w hurtowniach NPC lub pozwól graczom wytwarzać je w lokalizacjach przemysłowych. Warsztaty mechaniczne mogą kupować części hurtowo po cenach hurtowych i przechowywać je we wspólnym ekwipunku warsztatu, co oznacza, że właściciel musi zarządzać łańcuchem dostaw, aby biznes działał sprawnie. Ta dynamika popytu i podaży nadaje ogromną głębię rozgrywce roleplay.

Lakierowanie i usługi kosmetyczne

Lakierowanie to jedna z najbardziej satysfakcjonujących wizualnie usług, jakie może zaoferować warsztat mechanika, a jej dobre wdrożenie wymaga pracy z kilkoma funkcjami native kolorów pojazdów. FiveM oferuje nativy dla koloru głównego, koloru dodatkowego, perły, koloru kół oraz niestandardowych wartości RGB. Zbuduj UI wyboru kolorów, które pozwala mechanikowi wybierać spośród gotowych kolorów lub wprowadzać własne wartości RGB za dodatkową opłatą. NUI powinno wyświetlać podgląd w czasie rzeczywistym, tymczasowo nakładając kolor na pojazd, podczas gdy mechanik przegląda opcje. Oto jak obsłużyć nakładanie koloru po stronie serwera po potwierdzeniu lakierowania przez mechanika i opłaceniu usługi przez klienta:

RegisterNetEvent('mechanic:server:applyPaint', function(netId, paintData, customerId)
    local src = source
    local Mechanic = QBCore.Functions.GetPlayer(src)
    local Customer = QBCore.Functions.GetPlayer(customerId)

    if not Mechanic or not Customer then return end
    if Mechanic.PlayerData.job.name ~= 'mechanic' then return end

    local gradeServices = Config.MechanicGrades[Mechanic.PlayerData.job.grade.level].services
    if gradeServices ~= 'all' and not TableContains(gradeServices, 'spray_paint') then
        return TriggerClientEvent('QBCore:Notify', src, 'Not authorized', 'error')
    end

    local price = paintData.isCustomRGB and Config.ServicePrices.spray_paint * 1.5
        or Config.ServicePrices.spray_paint

    if Customer.Functions.RemoveMoney('cash', price, 'mechanic-paint') then
        local shopCut = math.floor(price * 0.6)
        local mechanicCut = price - shopCut
        Mechanic.Functions.AddMoney('cash', mechanicCut, 'mechanic-paint-commission')
        AddToShopFunds(Mechanic.PlayerData.job.grade.level >= 3 and src, shopCut)

        TriggerClientEvent('mechanic:client:applyPaint', customerId, netId, paintData)
        TriggerClientEvent('QBCore:Notify', src, 'Paint applied - earned $' .. mechanicCut, 'success')
        TriggerClientEvent('QBCore:Notify', customerId, 'Vehicle painted for $' .. price, 'success')
    else
        TriggerClientEvent('QBCore:Notify', src, 'Customer cannot afford this', 'error')
    end
end)

Oprócz podstawowego lakierowania warto rozważyć dodanie nakładania oklein (livery), montażu świateł neonowych i przyciemniania szyb jako osobnych usług kosmetycznych. Każda usługa powinna mieć własne wymagania dotyczące części i poziom cenowy. Na przykład światła neonowe wymagają zestawów neonów z ekwipunku części i korzystają z SetVehicleNeonLightEnabled i SetVehicleNeonLightsColour natives do zastosowania efektu wizualnego. Przyciemnianie szyb wykorzystuje SetVehicleWindowTint z różnymi poziomami przyciemnienia szyb, które mogą być ograniczone przez lokalne przepisy serwera, dając policji powód do zatrzymywania graczy za nielegalne przyciemnienie.

Ulepszenia osiągów i tuning

Tuning osiągów to obszar, w którym mechanicy mogą naprawdę zabłysnąć i zarobić najwięcej na serwerze. FiveM udostępnia rozbudowane natywne funkcje modyfikacji pojazdów poprzez SetVehicleMod funkcja, która przyjmuje mod type i mod index. Typy modyfikacji obejmują ulepszenia silnika (typ 11), hamulce (typ 12), skrzynię biegów (typ 13), zawieszenie (typ 15), pancerz (typ 16) oraz turbo (typ 18). Każdy typ modyfikacji ma kilka poziomów, które stopniowo poprawiają osiągi pojazdu. Zbuduj interfejs tuningu, który pokazuje dostępne ulepszenia dla danego pojazdu, koszt każdego poziomu, a najlepiej porównanie statystyk pokazujące wartości przed i po dla prędkości, przyspieszenia, hamowania i prowadzenia:

function GetAvailableUpgrades(vehicle)
    local upgrades = {}
    local modTypes = {
        {type = 11, label = 'Engine', icon = 'fa-engine'},
        {type = 12, label = 'Brakes', icon = 'fa-brake'},
        {type = 13, label = 'Transmission', icon = 'fa-gears'},
        {type = 15, label = 'Suspension', icon = 'fa-car'},
        {type = 16, label = 'Armor', icon = 'fa-shield'},
        {type = 18, label = 'Turbo', icon = 'fa-bolt'}
    }

    SetVehicleModKit(vehicle, 0)

    for _, mod in ipairs(modTypes) do
        local currentLevel = GetVehicleMod(vehicle, mod.type)
        local maxLevel = GetNumVehicleMods(vehicle, mod.type)
        local isTurbo = mod.type == 18

        table.insert(upgrades, {
            type = mod.type,
            label = mod.label,
            icon = mod.icon,
            currentLevel = currentLevel,
            maxLevel = isTurbo and 1 or maxLevel,
            installed = isTurbo and IsToggleModOn(vehicle, mod.type) or currentLevel >= 0,
            price = CalculateUpgradePrice(mod.type, currentLevel + 1)
        })
    end

    return upgrades
end

function ApplyPerformanceUpgrade(vehicle, modType, level)
    SetVehicleModKit(vehicle, 0)

    if modType == 18 then
        ToggleVehicleMod(vehicle, 18, true)
    else
        SetVehicleMod(vehicle, modType, level, false)
    end
end

Ulepszenia osiągów powinny wymagać wartościowych części, takich jak zestawy turbo, wyścigowe skrzynie biegów czy sportowe układy hamulcowe. Części te można pozyskiwać od wyspecjalizowanych dostawców lub wytwarzać przez graczy z odpowiednimi umiejętnościami, tworząc zależności między zawodami, które wzbogacają ekonomię serwera. Zawsze weryfikuj żądania ulepszeń po stronie serwera, aby uniemożliwić klientom stosowanie modyfikacji, za które nie zapłacili lub na które nie mają części.

System rozliczeń i podział przychodów

Przejrzysty system rozliczeń łączy całą rozgrywkę mechanika w spójną całość i obsługuje transakcje finansowe między mechanikiem, klientem a warsztatem. Gdy mechanik ukończy usługę, wygeneruj szczegółowy rachunek z wyszczególnionymi wykonanymi usługami i ich kosztami. Przedstaw rachunek klientowi za pomocą powiadomienia lub okna NUI, które musi zaakceptować przed przetworzeniem płatności. Podziel przychód między mechanika wykonującego pracę a konto firmowe warsztatu, przy czym proporcja podziału jest konfigurowana przez właściciela warsztatu. Oto system rozliczeniowy po stronie serwera, który obsługuje wystawianie faktur i przetwarzanie płatności:

local activeInvoices = {}

RegisterNetEvent('mechanic:server:createInvoice', function(customerId, services)
    local src = source
    local Mechanic = QBCore.Functions.GetPlayer(src)
    local Customer = QBCore.Functions.GetPlayer(customerId)

    if not Mechanic or not Customer then return end
    if Mechanic.PlayerData.job.name ~= 'mechanic' then return end

    local totalPrice = 0
    local lineItems = {}

    for _, service in ipairs(services) do
        local price = Config.ServicePrices[service.name]
        if price then
            totalPrice = totalPrice + price
            table.insert(lineItems, {
                name = service.label,
                price = price
            })
        end
    end

    local invoiceId = 'INV-' .. os.time() .. '-' .. math.random(1000, 9999)
    activeInvoices[invoiceId] = {
        mechanic = src,
        customer = customerId,
        total = totalPrice,
        items = lineItems,
        shopId = Mechanic.PlayerData.metadata.currentShop,
        timestamp = os.time()
    }

    TriggerClientEvent('mechanic:client:showInvoice', customerId, invoiceId, lineItems, totalPrice)
end)

RegisterNetEvent('mechanic:server:payInvoice', function(invoiceId)
    local src = source
    local invoice = activeInvoices[invoiceId]
    if not invoice or invoice.customer ~= src then return end

    local Customer = QBCore.Functions.GetPlayer(src)
    local Mechanic = QBCore.Functions.GetPlayer(invoice.mechanic)

    if Customer.Functions.RemoveMoney('cash', invoice.total, 'mechanic-invoice') then
        local mechanicShare = math.floor(invoice.total * 0.4)
        local shopShare = invoice.total - mechanicShare

        if Mechanic then
            Mechanic.Functions.AddMoney('cash', mechanicShare, 'mechanic-wage')
            TriggerClientEvent('QBCore:Notify', invoice.mechanic,
                'Received $' .. mechanicShare .. ' for services', 'success')
        end

        UpdateShopBalance(invoice.shopId, shopShare)
        activeInvoices[invoiceId] = nil

        TriggerClientEvent('QBCore:Notify', src, 'Paid $' .. invoice.total, 'success')
    else
        TriggerClientEvent('QBCore:Notify', src, 'Not enough cash', 'error')
    end
end)

Rozważ obsługę wielu metod płatności, w tym gotówki, przelewów bankowych, a nawet kryptowalut, jeśli twój serwer posiada system krypto. Rejestruj wszystkie transakcje w logach bazy danych, aby właściciele warsztatów mogli przeglądać historię przychodów, identyfikować najwydajniejszych mechaników i wykrywać podejrzane wzorce rozliczeń. To śledzenie finansów umożliwia także systemy podatkowe i interakcje roleplay z rządem, gdzie państwo może przeprowadzać audyty warsztatów mechanicznych.

Zarządzanie ekwipunkiem stashy i sklepów

Każdy warsztat mechanika potrzebuje wspólnego schowka (stash), w którym części są przechowywane i dostępne dla wszystkich pracowników na służbie. Zintegruj go z systemem ekwipunku na twoim serwerze, niezależnie od tego, czy jest to ox_inventory, qb-inventory, czy rozwiązanie autorskie, aby utworzyć schowek warsztatu dostępny tylko dla uprawnionych mechaników. Właściciel warsztatu powinien mieć możliwość zamawiania części u hurtownika NPC, co pobiera pieniądze z konta firmowego warsztatu i dodaje części do schowka po konfigurowalnym czasie dostawy. To opóźnienie symuluje realną logistykę łańcucha dostaw i zapobiega natychmiastowemu uzupełnianiu zapasów. Śledź dostęp do schowka w logach, aby właściciel warsztatu widział, który mechanik zabrał jakie części, co zapobiega kradzieżom wewnętrznym. Po stronie klienta użyj interakcji target na konkretnym propie w warsztacie, na przykład na szafce z narzędziami lub półce z częściami, aby otworzyć schowek. Połącz schowek z systemem craftingu, w którym mechanicy mogą składać złożone części z surowców, na przykład łącząc obudowę turbiny, wirnik i wastegate w kompletny zestaw turbo, co dodaje kolejny element oparty na umiejętnościach do tej pracy.

Holownik i pomoc drogowa

Rozszerzenie pracy mechanika o lawety i pomoc drogową znacznie zwiększa aktywność i potencjał zarobkowy tej profesji. Mechanicy powinni mieć możliwość pobrania lawety ze swojego warsztatu, dojechania do unieruchomionego gracza, podczepienia uszkodzonego pojazdu za pomocą AttachEntityToEntity native i odholować go do warsztatu w celu naprawy. Zaimplementuj system zgłoszeń, w którym gracze mogą wezwać pomoc drogową przez telefon, co tworzy blip na mapie widoczny dla wszystkich mechaników na służbie. Pierwszy mechanik, który zaakceptuje zgłoszenie, otrzymuje zlecenie, a trasa GPS jest wyznaczana do lokalizacji klienta. W systemie mocowania oblicz odpowiednie pozycje offsetu w zależności od modelu lawety, aby holowany pojazd stał prawidłowo na platformie. Dodaj opłatę zależną od odległości za usługę holowania, aby dłuższe trasy kosztowały klienta więcej, co zachęci mechaników do obsługi wezwań w ich okolicy, jednocześnie pozwalając im brać lukratywne zlecenia na duże odległości przez całą mapę.

Pasujący skrypt

Gotowe na twój serwer, aktualizacje w zestawie.

Gotowy, aby zacząć?

Kup skrypty w naszym sklepie lub dołącz do Discorda, aby uzyskać wsparcie, aktualizacje i sprawdzić nadchodzące nowości.