Skip to Content
Resourcesqb-mechanicjob – Vehicle Repair & Tuning Job for QBCore | FiveM Docs

QB-MechanicJob - Vehicle Repair & Tuning System

The qb-mechanicjob resource provides a comprehensive vehicle repair and tuning system for QBCore servers, featuring mechanic shops, vehicle customization, repair services, and towing operations.

Overview

QB-MechanicJob creates a realistic automotive service experience with vehicle repairs, custom tuning, paint jobs, performance modifications, and complete mechanic shop management. Players can operate as mechanics or customers seeking vehicle services.

If you want a marketplace option instead of extending the stock job, review a FiveM mechanic system  and test it on staging before replacing qb-mechanicjob.

Key Features

  • Mechanic Shops: Multiple workshop locations with full service capabilities
  • Vehicle Repairs: Engine, body, and component repair systems
  • Custom Tuning: Performance modifications and upgrades
  • Paint & Liveries: Vehicle customization and visual modifications
  • Towing Service: Flatbed and tow truck operations
  • Parts Inventory: Vehicle parts and supplies management
  • Service Billing: Customer invoicing and payment system
  • Shop Management: Business operations and employee management
  • Vehicle Diagnostics: Damage assessment and repair estimates

Installation

Prerequisites

  • QBCore Framework
  • qb-target (for interaction system)
  • qb-menu (for mechanic menus)
  • qb-input (for service forms)
  • qb-inventory (for vehicle parts)
  • qb-vehiclekeys (for key management)

Installation Steps

  1. Download the Resource
cd resources/[qb] git clone https://github.com/qbcore-framework/qb-mechanicjob.git
  1. Database Setup
-- Mechanic shop tables CREATE TABLE IF NOT EXISTS `mechanic_orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `citizenid` varchar(50) DEFAULT NULL, `mechanic` varchar(50) DEFAULT NULL, `vehicle_plate` varchar(50) DEFAULT NULL, `service_type` varchar(100) DEFAULT NULL, `parts_used` longtext DEFAULT NULL, `total_cost` int(11) DEFAULT 0, `status` varchar(50) DEFAULT 'pending', `created_at` timestamp DEFAULT current_timestamp(), PRIMARY KEY (`id`) ); CREATE TABLE IF NOT EXISTS `mechanic_parts` ( `id` int(11) NOT NULL AUTO_INCREMENT, `shop` varchar(50) DEFAULT NULL, `part_name` varchar(100) DEFAULT NULL, `quantity` int(11) DEFAULT 0, `cost` int(11) DEFAULT 0, `updated_at` timestamp DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`id`) ); CREATE TABLE IF NOT EXISTS `vehicle_modifications` ( `id` int(11) NOT NULL AUTO_INCREMENT, `plate` varchar(50) DEFAULT NULL, `modifications` longtext DEFAULT NULL, `performance_mods` longtext DEFAULT NULL, `last_modified` timestamp DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`id`), UNIQUE KEY `plate` (`plate`) ); CREATE TABLE IF NOT EXISTS `mechanic_invoices` ( `id` int(11) NOT NULL AUTO_INCREMENT, `citizenid` varchar(50) DEFAULT NULL, `shop` varchar(50) DEFAULT NULL, `services` longtext DEFAULT NULL, `amount` int(11) DEFAULT 0, `paid` tinyint(1) DEFAULT 0, `date` timestamp DEFAULT current_timestamp(), PRIMARY KEY (`id`) );
  1. Add Items to qb-core/shared/items.lua
-- Vehicle Parts ['engine_part'] = { ['name'] = 'engine_part', ['label'] = 'Engine Part', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'engine_part.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Engine component for vehicle repairs' }, ['transmission_part'] = { ['name'] = 'transmission_part', ['label'] = 'Transmission Part', ['weight'] = 800, ['type'] = 'item', ['image'] = 'transmission_part.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Transmission component' }, ['brake_pads'] = { ['name'] = 'brake_pads', ['label'] = 'Brake Pads', ['weight'] = 300, ['type'] = 'item', ['image'] = 'brake_pads.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Brake pads for vehicle repair' }, ['tire'] = { ['name'] = 'tire', ['label'] = 'Vehicle Tire', ['weight'] = 2000, ['type'] = 'item', ['image'] = 'tire.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Replacement vehicle tire' }, ['turbo_kit'] = { ['name'] = 'turbo_kit', ['label'] = 'Turbo Kit', ['weight'] = 5000, ['type'] = 'item', ['image'] = 'turbo_kit.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Performance turbo kit upgrade' }
  1. Add Job Configuration to qb-core/shared/jobs.lua
['mechanic'] = { label = 'Mechanic', defaultDuty = true, offDutyPay = false, grades = { ['0'] = { name = 'Apprentice', payment = 50 }, ['1'] = { name = 'Mechanic', payment = 75 }, ['2'] = { name = 'Advanced Mechanic', payment = 100 }, ['3'] = { name = 'Shop Supervisor', payment = 125, isboss = true }, ['4'] = { name = 'Shop Manager', payment = 150, isboss = true } } }
  1. Add to server.cfg
ensure qb-mechanicjob

Ensure qb-mechanicjob loads after qb-core, qb-target, and qb-inventory in your server.cfg

Configuration

Basic Configuration

The main configuration file is located at config.lua:

Config = {} -- General Settings Config.UseTarget = true Config.RepairCost = { body = 1000, engine = 1500, transmission = 1200, brakes = 800, suspension = 900 } -- Mechanic Shop Locations Config.Locations = { ["bennys"] = { label = "Benny's Original Motor Works", coords = vector3(-212.55, -1324.2, 30.89), blip = { sprite = 72, color = 17, scale = 0.8 }, zones = { duty = vector3(-212.55, -1324.2, 30.89), stash = vector3(-222.47, -1329.73, 30.89), vehicle = vector4(-229.47, -1315.39, 30.89, 270.0), lift1 = vector4(-212.0, -1308.0, 31.3, 270.0), lift2 = vector4(-212.0, -1318.0, 31.3, 270.0) } }, ["hayes"] = { label = "Hayes Autos", coords = vector3(-1419.24, -446.58, 35.91), blip = { sprite = 72, color = 17, scale = 0.8 }, zones = { duty = vector3(-1419.24, -446.58, 35.91), stash = vector3(-1413.35, -448.26, 35.91), vehicle = vector4(-1428.46, -455.12, 35.91, 120.0), lift1 = vector4(-1419.0, -450.0, 36.0, 120.0) } } } -- Tow Truck Spawn Points Config.TowSpawns = { [1] = vector4(-229.47, -1315.39, 30.89, 270.0), [2] = vector4(-228.47, -1320.39, 30.89, 270.0) } -- Vehicle Modification Costs Config.ModificationCosts = { engine = { [0] = 0, [1] = 5000, [2] = 10000, [3] = 15000, [4] = 25000 }, brakes = { [0] = 0, [1] = 2500, [2] = 5000, [3] = 7500 }, transmission = { [0] = 0, [1] = 4000, [2] = 8000, [3] = 12000 }, suspension = { [0] = 0, [1] = 3000, [2] = 6000, [3] = 9000, [4] = 12000 }, turbo = 15000, armor = { [0] = 0, [1] = 5000, [2] = 10000, [3] = 15000, [4] = 20000, [5] = 25000 } }

Vehicle Damage System

-- Damage Thresholds Config.DamageSystem = { engine = { threshold = 650.0, repairCost = 1500, parts = {"engine_part"} }, body = { threshold = 800.0, repairCost = 1000, parts = {"body_panel"} }, transmission = { threshold = 700.0, repairCost = 1200, parts = {"transmission_part"} }, brakes = { threshold = 750.0, repairCost = 800, parts = {"brake_pads"} }, tires = { threshold = 900.0, repairCost = 400, parts = {"tire"} } } -- Repair Requirements Config.RepairRequirements = { mechanic_level = { basic = 0, -- Apprentice can do basic repairs advanced = 2, -- Advanced Mechanic for complex repairs custom = 3 -- Supervisor+ for custom modifications }, tools_required = { basic = {"wrench", "screwdriver"}, advanced = {"diagnostic_tool", "hydraulic_jack"}, custom = {"tuning_laptop", "dyno_access"} } }

Parts and Pricing

-- Vehicle Parts Configuration Config.Parts = { ["engine_part"] = { label = "Engine Component", cost = 500, category = "engine", required_skill = 1 }, ["transmission_part"] = { label = "Transmission Component", cost = 400, category = "transmission", required_skill = 1 }, ["brake_pads"] = { label = "Brake Pads", cost = 200, category = "brakes", required_skill = 0 }, ["tire"] = { label = "Performance Tire", cost = 300, category = "tires", required_skill = 0 }, ["turbo_kit"] = { label = "Turbo Kit", cost = 2500, category = "performance", required_skill = 3 } } -- Service Pricing Config.ServicePrices = { oil_change = 150, tire_repair = 100, brake_service = 300, engine_tune = 500, full_service = 800, custom_paint = 1200, performance_tune = 2000 }

API Reference

Client Exports

RepairVehicle

Repair a vehicle with specified components.

-- Repair specific component exports['qb-mechanicjob']:RepairVehicle(vehicle, "engine") -- Repair multiple components exports['qb-mechanicjob']:RepairVehicle(vehicle, {"engine", "body", "brakes"}) -- Full repair exports['qb-mechanicjob']:RepairVehicle(vehicle, "all") -- Parameters: -- vehicle: Vehicle entity -- components: String or table of components to repair

GetVehicleDamage

Get detailed damage information for a vehicle.

local damageInfo = exports['qb-mechanicjob']:GetVehicleDamage(vehicle) -- Returns: -- { -- engine = number (0-1000), -- body = number (0-1000), -- transmission = number (0-1000), -- brakes = number (0-1000), -- tires = table of tire conditions -- }

ModifyVehicle

Apply performance modifications to a vehicle.

-- Apply single modification exports['qb-mechanicjob']:ModifyVehicle(vehicle, "engine", 2) -- Apply multiple modifications exports['qb-mechanicjob']:ModifyVehicle(vehicle, { engine = 2, brakes = 1, suspension = 1, turbo = true }) -- Parameters: -- vehicle: Vehicle entity -- modifications: Modification type and level

Server Exports

CreateServiceOrder

Create a new service order for a customer.

local orderId = exports['qb-mechanicjob']:CreateServiceOrder(data) -- Parameters: -- data: { -- citizenid = string, -- mechanic = string, -- vehicle_plate = string, -- services = table, -- total_cost = number -- }

ProcessPayment

Process payment for mechanic services.

local success = exports['qb-mechanicjob']:ProcessPayment(source, amount, description) -- Parameters: -- source: Player server ID -- amount: Payment amount -- description: Service description

UpdatePartInventory

Update shop part inventory.

exports['qb-mechanicjob']:UpdatePartInventory(shop, partName, quantity) -- Parameters: -- shop: Shop identifier -- partName: Part name -- quantity: Quantity change (+/-)

GetShopInventory

Get current shop inventory.

local inventory = exports['qb-mechanicjob']:GetShopInventory(shop) -- Returns table of parts and quantities

Events

Client Events

-- Vehicle repair started RegisterNetEvent('qb-mechanicjob:client:repairStarted', function(repairType) -- Handle repair start end) -- Vehicle modification applied RegisterNetEvent('qb-mechanicjob:client:modificationApplied', function(modType, level) -- Handle modification end) -- Service order created RegisterNetEvent('qb-mechanicjob:client:orderCreated', function(orderId) -- Handle new order end) -- Payment processed RegisterNetEvent('qb-mechanicjob:client:paymentProcessed', function(amount) -- Handle payment completion end)

Server Events

-- Mechanic on/off duty RegisterNetEvent('qb-mechanicjob:server:dutyToggle', function(onDuty) -- Handle duty status change end) -- Vehicle towed RegisterNetEvent('qb-mechanicjob:server:vehicleTowed', function(plate, location) -- Handle vehicle towing end) -- Parts ordered RegisterNetEvent('qb-mechanicjob:server:orderParts', function(parts, shop) -- Handle parts ordering end) -- Service completed RegisterNetEvent('qb-mechanicjob:server:serviceCompleted', function(orderId, services) -- Handle service completion end)

Usage Examples

Vehicle Repair System

-- Client-side repair process RegisterNetEvent('qb-mechanicjob:client:startRepair', function(repairType) local player = QBCore.Functions.GetPlayerData() if player.job.name == "mechanic" and player.job.onduty then local vehicle = QBCore.Functions.GetClosestVehicle() local requiredParts = Config.DamageSystem[repairType].parts -- Check if mechanic has required parts for i = 1, #requiredParts do local hasPart = QBCore.Functions.HasItem(requiredParts[i]) if not hasPart then QBCore.Functions.Notify("Missing required part: " .. requiredParts[i], "error") return end end -- Start repair animation and progress QBCore.Functions.Progressbar("vehicle_repair", "Repairing " .. repairType .. "...", 10000, false, true, { disableMovement = true, disableCarMovement = true, disableMouse = false, disableCombat = true, }, { animDict = "mini@repair", anim = "fixing_a_ped", }, { model = "prop_tool_box_04", bone = 57005, coords = vector3(0.4, 0.0, 0.0), rotation = vector3(0.0, 0.0, 0.0), }, {}, function() -- Repair completed TriggerServerEvent('qb-mechanicjob:server:repairVehicle', VehToNet(vehicle), repairType) end) end end) -- Server-side repair handler RegisterNetEvent('qb-mechanicjob:server:repairVehicle', function(netId, repairType) local src = source local player = QBCore.Functions.GetPlayer(src) local vehicle = NetworkGetEntityFromNetworkId(netId) if player.PlayerData.job.name == "mechanic" then local repairCost = Config.RepairCost[repairType] or 500 local requiredParts = Config.DamageSystem[repairType].parts -- Remove required parts from inventory for i = 1, #requiredParts do player.Functions.RemoveItem(requiredParts[i], 1) end -- Apply repair to vehicle if repairType == "engine" then SetVehicleEngineHealth(vehicle, 1000.0) elseif repairType == "body" then SetVehicleBodyHealth(vehicle, 1000.0) elseif repairType == "brakes" then SetVehicleBrake(vehicle, false) end TriggerClientEvent('QBCore:Notify', src, repairType .. ' repaired successfully!', 'success') end end)

Vehicle Modification System

-- Performance tuning interface RegisterNetEvent('qb-mechanicjob:client:openTuningMenu', function() local vehicle = QBCore.Functions.GetClosestVehicle() if not vehicle then return end local tuningMenu = { { header = "Vehicle Tuning", isMenuHeader = true }, { header = "Engine Upgrade", txt = "Improve engine performance", params = { event = "qb-mechanicjob:client:upgradeEngine", args = {vehicle = vehicle} } }, { header = "Brake System", txt = "Upgrade brake system", params = { event = "qb-mechanicjob:client:upgradeBrakes", args = {vehicle = vehicle} } }, { header = "Suspension", txt = "Modify suspension", params = { event = "qb-mechanicjob:client:upgradeSuspension", args = {vehicle = vehicle} } }, { header = "Turbo Kit", txt = "Install turbo kit - $" .. Config.ModificationCosts.turbo, params = { event = "qb-mechanicjob:client:installTurbo", args = {vehicle = vehicle} } } } exports['qb-menu']:openMenu(tuningMenu) end) -- Engine upgrade implementation RegisterNetEvent('qb-mechanicjob:client:upgradeEngine', function(data) local vehicle = data.vehicle local currentLevel = GetVehicleMod(vehicle, 11) -- Engine mod local nextLevel = currentLevel + 1 if nextLevel <= 4 then local cost = Config.ModificationCosts.engine[nextLevel] QBCore.Functions.TriggerCallback('qb-mechanicjob:server:canAfford', function(canAfford) if canAfford then SetVehicleMod(vehicle, 11, nextLevel, false) TriggerServerEvent('qb-mechanicjob:server:payForMod', cost, 'Engine Upgrade Level ' .. nextLevel) else QBCore.Functions.Notify("Insufficient funds for upgrade", "error") end end, cost) else QBCore.Functions.Notify("Engine already at maximum level", "error") end end)

Towing Service

-- Tow truck operations RegisterNetEvent('qb-mechanicjob:client:towVehicle', function() local player = QBCore.Functions.GetPlayerData() if player.job.name == "mechanic" and player.job.onduty then local towTruck = GetVehiclePedIsIn(PlayerPedId(), false) local towModel = GetEntityModel(towTruck) -- Check if player is in a tow truck if towModel == GetHashKey("flatbed") or towModel == GetHashKey("towtruck") then local targetVehicle = QBCore.Functions.GetClosestVehicle() if targetVehicle then QBCore.Functions.Progressbar("towing_vehicle", "Attaching vehicle to tow truck...", 8000, false, true, { disableMovement = true, disableCarMovement = true, disableMouse = false, disableCombat = true, }, { animDict = "mini@repair", anim = "fixing_a_ped", }, {}, {}, function() AttachEntityToEntity(targetVehicle, towTruck, 0, 0.0, -2.5, 1.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) QBCore.Functions.Notify("Vehicle attached to tow truck", "success") end) else QBCore.Functions.Notify("No vehicle nearby to tow", "error") end else QBCore.Functions.Notify("You need to be in a tow truck", "error") end end end)

Troubleshooting

Common Issues

Vehicle Repairs Not Working

-- Check vehicle entity validity if not DoesEntityExist(vehicle) then print("Vehicle entity does not exist") return end -- Verify repair permissions local player = QBCore.Functions.GetPlayerData() if player.job.name ~= "mechanic" or not player.job.onduty then print("Player not authorized for repairs") return end

Modification Costs Not Updating

  • Verify modification cost configuration in config.lua
  • Check if vehicle model supports specific modifications
  • Ensure proper database table structure for tracking modifications

Parts Inventory Issues

-- Debug parts inventory RegisterCommand('checkparts', function() local inventory = exports['qb-mechanicjob']:GetShopInventory('bennys') for part, quantity in pairs(inventory) do print(part .. ": " .. quantity) end end)

Debug Commands

-- Repair vehicle instantly (admin only) /fixveh -- Add mechanic parts to inventory /givepart [part_name] [quantity] -- Check vehicle modification levels /checkmods -- Toggle mechanic duty /mechduty

Performance Optimization

  1. Damage Calculations: Optimize vehicle damage checking frequency
  2. Part Inventory: Cache inventory data to reduce database queries
  3. Vehicle Spawning: Implement proper vehicle cleanup and pooling

Always test vehicle modifications and repairs thoroughly to ensure they work correctly with your server’s vehicle system.

Last updated on