NR_Harness

A professional vehicle modification script with multi-framework support (ESX, QBCore, QBX) that allows authorized mechanics to install and remove racing harnesses with persistent database storage.

Features

Dependencies

Resource Description Required
es_extended / qb-core / qbx_core Core framework (auto-detected) One of these
ox_lib UI library (context menus, progress bars, notifications) Yes
Inventory system ox_inventory, qb-inventory, ps-inventory, lj-inventory, codem-inventory, core_inventory, origen_inventory, and more (auto-detected) One of these
ox_target / qb-target Target/interaction system (auto-detected) One of these
oxmysql Database connector Yes

Installation

Step 1: Database Setup

Execute the included SQL file to create the vehicle_harnesses table. This stores all harness installations persistently.

Step 2: Download

Download NR_Harness and extract it to your resources folder:

server/
  └── resources/
      └── [echo]/
          └── NR_Harness/

Step 3: server.cfg

Add the resource to your server configuration:

ensure NR_Harness

Step 4: Add Inventory Item

Add a harness item to your inventory system. Choose the format that matches your setup:

ox_inventory — Add to ox_inventory/data/items.lua:

['harness'] = {
    label = 'Racing Harness',
    weight = 2500,
    stack = false,
    close = true,
    description = 'A racing harness for improved vehicle safety'
}

qb-core — Add to qb-core/shared/items.lua:

harness = { name = 'harness', label = 'Racing Harness', weight = 2500, type = 'item', image = 'harness.png', unique = false, useable = true, shouldClose = true, description = 'A racing harness for improved vehicle safety' },

Step 5: Configure

Edit config.lua to set authorized jobs, harness item name, and installation/removal times.

Step 6: Restart

Restart your server to load the resource.

💡 Framework Auto-Detection

NR_Harness automatically detects your framework (ESX, QBCore, or QBX) at startup. No manual configuration needed — just ensure your framework is started before this resource. You can override this with Config.Framework if needed.

⚠️ Dependencies

Make sure your framework (es_extended, qb-core, or qbx_core), ox_lib, ox_inventory, ox_target, and oxmysql are all started before NR_Harness in your server.cfg.

How It Works

1. Obtaining Harnesses

Mechanics receive or purchase harness items. Items are stored in your inventory system like normal.

2. Installation Process

Mechanic approaches a vehicle (within 3 meters default) and uses /harness or ox_target on the vehicle. Select "Install Racing Harness" from the menu. A 10-second progress bar plays with a repair animation. The harness item is consumed from inventory, the installation is saved to the database, and all clients are notified of the harness status.

3. Removal Process

Mechanic approaches a vehicle that has a harness and uses /harness or ox_target. Select "Remove Racing Harness". An 8-second progress bar plays with a repair animation. The harness is removed from the database, the item is returned to inventory (if configured), and all clients are notified of the status change.

Database Schema

vehicle_harnesses
├── id (INT) - Primary key
├── plate (VARCHAR) - Vehicle plate (unique)
└── installed_at (TIMESTAMP) - Installation date/time

Features a unique constraint on plate (one harness per vehicle), indexed plate column for fast lookups, timestamp tracking for installation history, and ON DUPLICATE KEY UPDATE for reinstallation handling.

Configuration

Framework

-- 'auto' detects your framework automatically (recommended)
-- Manual options: 'esx', 'qb', 'qbx'
Config.Framework = 'auto'

Job Permissions

Config.Jobs = {
    'flywheel',      -- Mechanic shop 1
    'afterlife',     -- Mechanic shop 2
    'bennys',        -- Add more as needed
}

Item Settings

Config.HarnessItem = 'harness'  -- Item name in your inventory system

Distance & Timing

Config.InstallDistance = 3.0  -- Meters from vehicle

Config.HarnessSettings = {
    installTime = 10000,  -- 10 seconds
    removeTime = 8000,    -- 8 seconds
    returnItemOnRemove = true,  -- Give item back when removing
}

Custom Notifications

Config.Notifications = {
    installSuccess = 'Racing harness installed successfully!',
    removeSuccess = 'Racing harness removed successfully!',
    alreadyInstalled = 'This vehicle already has a harness installed!',
    noHarness = 'This vehicle does not have a harness installed!',
    noItem = 'You need a racing harness to install!',
    wrongJob = 'You are not qualified to install/remove harnesses!',
    cancelled = 'Installation cancelled!',
    vehicleNotFound = 'No vehicle found nearby!',
}

Integration with Other Scripts

Export: Check Harness Status

Other scripts can check if a vehicle has a harness installed:

local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
local hasHarness = exports['NR_Harness']:hasHarness(vehicle)

if hasHarness then
    -- Apply harness benefits (reduced ejection, etc.)
else
    -- Normal vehicle behavior
end

Example: Ejection Prevention

CreateThread(function()
    while true do
        Wait(100)
        local ped = PlayerPedId()

        if IsPedInAnyVehicle(ped, false) then
            local vehicle = GetVehiclePedIsIn(ped, false)
            local hasHarness = exports['NR_Harness']:hasHarness(vehicle)

            if hasHarness then
                SetPedConfigFlag(ped, 32, false) -- Disable exit on impact
            end
        end
    end
end)

Example: Racing Script Integration

AddEventHandler('baseevents:onPlayerWasted', function()
    local ped = PlayerPedId()
    if IsPedInAnyVehicle(ped, false) then
        local vehicle = GetVehiclePedIsIn(ped, false)
        local hasHarness = exports['NR_Harness']:hasHarness(vehicle)

        if hasHarness then
            SetEntityHealth(ped, GetEntityHealth(ped) + 50)
        end
    end
end)

Common use cases:

Security Features

Server-Side Validation

Protection Description
Job verification Every action double-checks job permission, prevents client-side exploits
Item possession Validates harness item via ox_inventory:Search() before installation
Database integrity UNIQUE constraint on plate prevents duplicates, ON DUPLICATE KEY UPDATE handles edge cases
State validation Checks if harness exists before install/remove, prevents impossible state transitions

Client-Side Protection

Customization

Adding More Jobs

Config.Jobs = {
    'mechanic',
    'tuner',
    'customs',
    'garage',
}

Custom Animations

Modify the animation in progress circles:

anim = {
    dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@',
    clip = 'machinic_loop_mechandplayer'
}

Popular mechanic animations:

Different Item Per Job

Modify the item check in server.lua:

local itemToUse = Config.HarnessItem
local jobName = Framework.GetPlayerJob(source)
if jobName == 'premium_mechanic' then
    itemToUse = 'premium_harness'
end

Commands

Command Description Permission
/harness Open harness installation menu for nearest vehicle Configured jobs only

Performance

Metric Value
Resmon impact ~0.00ms (idle), ~0.01ms (in vehicle check)
Network traffic Minimal (event on install/remove only)
Database queries 1 on resource start (load all), 1 per install/remove
Memory usage ~0.8 MB
Threads 1 (vehicle entry detection)

Database Maintenance

-- Check harness count
SELECT COUNT(*) FROM vehicle_harnesses;

-- List all harnessed vehicles
SELECT plate, installed_at FROM vehicle_harnesses ORDER BY installed_at DESC;

-- Remove harness from specific vehicle
DELETE FROM vehicle_harnesses WHERE plate = 'ABC123';

-- Clear old harnesses (vehicles likely deleted)
DELETE FROM vehicle_harnesses WHERE installed_at < DATE_SUB(NOW(), INTERVAL 90 DAY);

Troubleshooting

Framework not detected

Harness not installing

Database errors

ox_target not showing option

Harness status not updating

Item not returning on removal

Wrong vehicle getting harness

Support

Need help? Join our Discord server for community support and updates.