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
- Multi-framework support - Auto-detects ESX, QBCore, or QBX with optional manual override
- Job-restricted access - Only specified mechanic jobs can install/remove harnesses
- Persistent storage - MySQL database tracks harness installations by vehicle plate
- ox_target integration - Clean third-eye interaction system for vehicle modifications
- Command alternative -
/harnesscommand for quick access - Progress animations - Realistic installation/removal animations with progress circles
- Item management - Requires harness item in your inventory system
- Optional item return - Configurable to return harness item when removed
- Network synced - All players see harness status updates in real-time
- Export function - Other scripts can check if a vehicle has a harness
- Proximity detection - Automatic vehicle detection within configurable distance
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.
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.
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:
- Crash/rollover scripts reducing ejection chance
- Racing scripts providing safety bonuses
- Injury systems reducing damage
- Insurance scripts affecting premiums
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
- Job requirement - ox_target and command only work for authorized jobs
- Progress cancellation - Player can cancel, no item consumed, clean rollback
- Distance enforcement - Vehicle must be within configured range via
lib.getClosestVehicle()
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:
mini@repair / fixing_a_player(default)amb@prop_human_bum_bin@idle_a / idle_aanim@amb@clubhouse@tutorial@bkr_tut_ig3@ / machinic_loop_mechandplayer
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
- Ensure your framework (es_extended, qb-core, or qbx_core) is started before NR_Harness
- Check server console for
[NR_Harness] No supported framework detected - Try setting
Config.Frameworkmanually to'esx','qb', or'qbx' - Enable
Config.Debug = trueto see which framework was detected at startup
Harness not installing
- Verify player has an authorized job
- Check if harness item is in inventory
- Confirm item name matches
Config.HarnessItem - Check server console for SQL errors
Database errors
- Ensure oxmysql is running
- Verify SQL table was created correctly
- Check database connection in
server.cfg
ox_target not showing option
- Confirm your target system (ox_target or qb-target) is started before this resource
- Verify player has one of the configured jobs
- Check if within
Config.InstallDistance
Harness status not updating
- Verify all clients received the network event
- Check client console for errors
- Restart resource on all clients
Item not returning on removal
- Check
Config.HarnessSettings.returnItemOnRemoveis set totrue - Verify inventory isn't full
- Check server console for inventory errors
Wrong vehicle getting harness
- Plates are case-sensitive and space-sensitive
- Script auto-trims spaces, but custom plates may have issues
- Check database for duplicate plate entries
Support
Need help? Join our Discord server for community support and updates.