Page

About

This is a multipurpose handling system that will allow you to do the finest adjustments on vehicles parameters with an easy to use user interface, developer tool and advanced Drift Mode. The system will suit any type of server, no matter if it is a roleplay (where it could be used as a tuning tablet), freeroam, drift or racing where it could serve as a utility for players to freely adjust their cars or just as a developer tool with a feature that generates an XML code to just copy and drop into your server files.

For a roleplay server it can open variety of new scenarios, making each individual vehicle feel unique. You want Ford Mustang be stable on the road. With good skills you will be able to achieve it. You want it to be as drift car? Do it!

With our unique and advanced Drift System, you can make any upgraded car slide sideways easily. On top of that each player can configure the drift mode that suits them.

Installation

Installation difficulty

🟠⚫⚫⚫⚫

If you have any difficulties with resource installation you could ask for our services on our Discord server by creating a ticket.

1 - Add the script

  • Download the resource from cfx keymaster;

  • Unzip the resource archive;

  • Add the script to your resources folder;

  • Add db_qbcore.sql or db_esx.sql (depending on your framework) to your database, or do not add any sql, but in such case make sure to set Config.UseDatabaseHandlingSaving and Config.UseDatabasePresetsSaving to false;

  • Add the resource to your server start file (server.cfg) by writing ensure sb-handlingtuning. Make sure it is started after any dependencies you will be using.

2 - Adjust configs

Adjust files found in the /configs folder to fit your server.

Make sure to go through all options in /configs/config.lua and read the commented code to adjust the config to fit your server.

Most important settings are under the Framework section.

3 - Save Standard Vehicles handlings

If you change vehicles handlings in your server files make sure to repeat the step again!

This step is not necessary but highly recommended and it only needs to be done once.

  • After the resource is started join the game;

  • Make sure you have admin permissions for the resource;

  • Make sure you have added all your addon vehicles to Config.AddonVehicles table in the configs/config.lua file before doing next step;

  • Use command /fetchstandard in client side and wait until all vehicles are loaded (you will see an amount of them increasing);

If you will not do this, the script might set incorrect values to vehicles and show incorrect values in the tabled UI. If you will not add all your addon vehicles models to Config.AddonVehicles script will try to do that automatically when car is spawned, but it might aswell corrupt the data.

Config

Config = {}

-- 88888888b                                                                    dP       
-- 88                                                                           88       
-- a88aaaa    88d888b. .d8888b. 88d8b.d8b. .d8888b. dP  dP  dP .d8888b. 88d888b. 88  .dP  
-- 88        88'  `88 88'  `88 88'`88'`88 88ooood8 88  88  88 88'  `88 88'  `88 88888"   
-- 88        88       88.  .88 88  88  88 88.  ... 88.88b.88' 88.  .88 88       88  `8b. 
-- dP        dP       `88888P8 dP  dP  dP `88888P' 8888P Y8P  `88888P' dP       dP   `YP 
                                                                                                                                                                          
Config.Framework = 'qbcore' -- qbcore/esx/exm/other

Config.MySQLScript = 'MySQL' -- MySQL / oxmysql

Config.NotificationSystem = 'qbcore' -- qbcore / esx / custom

-- Identifier used to save/load player's presets in database
Config.PlayerIdentifier = 'license' -- license / steam / discord / ip

Config.UseDatabaseHandlingSaving = true
Config.UseDatabasePresetsSaving = true

Config.UseVstancer = true

-- Owned vehicles table in database information.
-- tableName - Name of table in which all owned vehicles are stored
-- ownerColumn - Owned vehicles owner column in DB table
-- plateColumn - Vehicle plate column in DB table
if Config.Framework == 'qbcore' then
    Config.OwnedVehiclesDataTable = {
        tableName = 'player_vehicles', ownerColumn = 'citizenid', plateColumn = 'plate' -- QBCore
    }
elseif Config.Framework == 'esx' or Config.Framework == 'exm' then
    Config.OwnedVehiclesDataTable = {
        tableName = 'owned_vehicles', ownerColumn = 'owner', plateColumn = 'plate' -- ESX
    }
else
    Config.OwnedVehiclesDataTable = {}
    Config.UseDatabaseHandlingSaving = false
    Config.UseDatabasePresetsSaving = false
end

-- .d888888                                               
-- d8'    88                                               
-- 88aaaaa88a .d8888b. .d8888b. .d8888b. .d8888b. .d8888b. 
-- 88     88  88'  `"" 88'  `"" 88ooood8 Y8ooooo. Y8ooooo. 
-- 88     88  88.  ... 88.  ... 88.  ...       88       88 
-- 88     88  `88888P' `88888P' `88888P' `88888P' `88888P'                                                     
                                                        
-- Admins and their checks
Config.Admins = {
    {type = 'identifier', data = 'steam:*'},
    {type = 'frameworkgroup', data = 'god'},
    {type = 'frameworkgroup', data = 'superadmin'},
    {type = 'frameworkgroup', data = 'admin'},
    {type = 'ace', data = 'handlingtuning'},
    {type = 'ace', data = 'acommands'},
}

-- NOT recommended for RolePlay server
-- If set to true players will be able to fully adjust their vehicle
-- and make it as crazy fast as they want.
Config.AllowEveryoneFullAccess = false

-- Limited editing allows for all players to use the tablet, but only adjust vehicles handling values for limited number
-- You can adjust how much of each field can be changed by editing configs/config.js Min / Max > changeLimit
--
-- For example if vehicle's standard mass is 2000, Min.changeLimit is 200 and Max.changeLimit is 500,
-- then player will have 1800 - 2500 to play around with, as 2000 - 200 = 1800, 2000 + 500 = 2500.
--
-- THIS WILL NOT AFFECT TABLET VALUES FOR ADMINS - TABLET DEV USAGE
Config.AllowLimitedEditing = true

-- If value in config.js is not added, this will be used instead
Config.DefaultChangeLimit = 0.1

-- Name of inventory item
-- FOR QBCORE:
-- ADD TO qb-core/shared.lua  >  QBShared.Items
-- ['tunertablet'] 			 		 = {['name'] = 'tunertablet', 				['label'] = 'Tuner Tablet', 			['weight'] = 1000, 		['type'] = 'item', 		['image'] = 'tablet.png', 				['unique'] = false, 	['useable'] = true, 	['shouldClose'] = true,    ['combinable'] = nil,   ['description'] = 'Tablet used to adjust vehicle handling data'},
-- FOR ESX/EXM:
-- ADD TO database
-- INSERT INTO `items` (name, label)
-- VALUES ('tunertablet', 'Tuning Tablet');
Config.TabletItemName = 'tunertablet'

-- Command for admins full tablet access
Config.TabletCommand = 'tablet'

-- If you want any field to not be accessible by any regular player add it here
Config.BlacklistedFields = {
    'nMonetaryValue',
    'fPetrolTankVolume',
}

-- Handling groups and their parameters.
-- Params define what car modification(s) is/are needed for the value to be changable.
-- Available mods names: Engine, Suspension, Transmission, Spoiler, FrontBumper, RearBumper, Armor
Config.HandlingGroups = {
    {
        Label = 'Engine', Params = {
            Engine = 2,
            Suspension = false,
            Transmission = false,
            Spoiler = false,
            FrontBumper = false,
            RearBumper = false,
        }
    },
    {
        Label = 'Suspension', Params = {
            Engine = false,
            Suspension = 3,
            Transmission = false,
            Spoiler = false,
            FrontBumper = false,
            RearBumper = false,
            
        }
    },
    {
        Label = 'Stance', Params = {
            Engine = false,
            Suspension = 3,
            Transmission = false,
            Spoiler = false,
            FrontBumper = false,
            RearBumper = false,
            
        }
    },
    {
        Label = 'Traction', Params = {
            Engine = false,
            Suspension = 2,
            Transmission = false,
            Spoiler = false,
            FrontBumper = false,
            RearBumper = false,
            
        }
    },
    {
        Label = 'Aero', Params = {
            Engine = false,
            Suspension = false,
            Transmission = false,
            Spoiler = 1,
            FrontBumper = 1,
            RearBumper = 1,
        
        }
    },
    {
        Label = 'Damage', Params = {
            Engine = false,
            Suspension = false,
            Transmission = false,
            Spoiler = false,
            FrontBumper = false,
            RearBumper = false,
            Armor = 4,
        }
    },
    {
        Label = 'Brakes', Params = {Brakes = 4}
    },
    { -- Other is needed.
        Label = 'Other', Params = {}
    },
}

-- Scores to be displayed in diagram for the tablet
local handlingConfig = {}
Citizen.CreateThread(function()
    Citizen.Wait(100)
    if not IsDuplicityVersion() then
        handlingConfig = exports[GetCurrentResourceName()].getHandlingConfig()
        Config.ScoreValues = {
            {label = 'Aero', field = 'fDownforceModifier', max = handlingConfig.fDownforceModifier.Max.value},
            {label = 'TopSpeed', field = 'fInitialDriveMaxFlatVel', max = handlingConfig.fInitialDriveMaxFlatVel.Max.value},
            {label = 'Braking', field = 'fBrakeForce', max = handlingConfig.fBrakeForce.Max.value},
            {label = 'Acceleration', field = {'fInitialDriveForce', 'fDriveInertia'}, max = handlingConfig.fInitialDriveForce.Max.value + handlingConfig.fDriveInertia.Max.value},
        }
    end
end)

-- If you want specific field to require specific mod add it here
-- Available mods names: Engine, Suspension, Transmission, Spoiler, FrontBumper, RearBumper, Armor
Config.RequirementsForFields = {
    fSuspensionRaise = {
        Transmission = 4
    } 
}

-- Your addon vehicles models
Config.AddonVehicles = {
    'bmwe3',
    'x6m',
    'c63coupe',
    'RS72020',
    'mach1',
    'z419',
    '635',
    'rs7',
    'rs615',
    'rmodrs7',
    'e21',
    'bmwe32',
    'e34touring',
    'e34',
    'e36prb',
    'bmwe39',
    'm3kean',
    'rmodmi8lb',
    'm2',
    'm3f80',
}

Config.MaximumFetchBuffer = 3

-- 888888ba           oo .8888b   dP       8888ba.88ba                 dP          
-- 88    `8b             88   "   88       88  `8b  `8b                88          
-- 88     88 88d888b. dP 88aaa  d8888P     88   88   88 .d8888b. .d888b88 .d8888b. 
-- 88     88 88'  `88 88 88       88       88   88   88 88'  `88 88'  `88 88ooood8 
-- 88    .8P 88       88 88       88       88   88   88 88.  .88 88.  .88 88.  ... 
-- 8888888P  dP       dP dP       dP       dP   dP   dP `88888P' `88888P8 `88888P' 

Config.DriftModeEnabled = true
-- Modifications required for Drift mode to be enabled
Config.DriftGroupParams = {
    Engine = 2,
    Suspension = 3,
    Transmission = 2,
}

-- Drift mode parameters.
-- label, description - what is displayed in tablet under the Drift group configuration
-- formula - formula used to calculate changes for the field when vehicle is moving sideways
Config.DriftModeFields = {
    fInitialDriveForce = {
        label = 'Drive Force multiplier on slide',
        description = 'How much of drive force will be increased when vehicle slides',
        formula = function(defaultValue, speed, angle, multiplier) 
            local result = defaultValue + angle/15
            return result
        end},
        fSteeringLock = {
        label = 'Steering lock multiplier on slide',
        formula = function(defaultValue, speed, angle, multiplier) 
            local result = math.max(defaultValue, math.min(defaultValue  + angle, 70.0))
            return result
        end},
        fTractionCurveMin = {
        label = 'Traction decrease multiplier on slide',
        formula = function(defaultValue, speed, angle, multiplier) 
            local result = math.max(defaultValue  - angle/17, 1.0)
            return result
        end},
        fDriveBiasFront = {
        label = 'Drive bias multiplier on slide',
        formula = function(defaultValue, speed, angle, multiplier) 
            local result = math.max(defaultValue, 0.2)
            return result
        end},
}

table.has = function(t, e)
    for _,v in ipairs(t) do
        if e == v then
            return true
        end
    end
    return false
end

table.count = function(t)
    local count = 0
    for _,__ in pairs(t) do
        count = count + 1
    end
    return count
end

table.clone = function(t)
    if type(t) ~= 'table' then return t end

	local meta = getmetatable(t)
	local target = {}

	for k,v in pairs(t) do
		if type(v) == 'table' then
			target[k] = table.clone(v)
		else
			target[k] = v
		end
	end

	setmetatable(target, meta)

	return target
end

How to use

Option 1 - Full access

You can use the handling tuning system with full access using a chat command /tablet. For players to have access to the command you need to give access using any of Config.Admins permissions. This will allow players to access all the features of the system including:

  • All handling parameters to be adjusted without any limit (in the range set in config.js);

  • Change parameters in all groups on any vehicle, without needing to upgrade the vehicle first;

  • Access Drift mode on any vehicle;

  • Ability to generate and copy XML file of vehicle's handling;

  • Access to either Minimal or Tablet UIs;

  • Adjust owned vehicles and have their values saved to database.

Option 2 - Limited access

Recommended for RP servers. You can allow players to use an inventory item to access the Tablet UI and adjust their vehicles in a limited range, which depends on original vehicle handling. This method will allow players to access their, or others vehicles to their liking and will include:

  • A limited parameters range (limits can be set in config.js);

  • Access to Drift mode if vehicle meets upgrades requirements;

  • Access to all handling groups if vehicle meets upgrades requirements;

  • Access to either Minimal or Tablet UIs;

  • Adjust owned vehicles and have their values saved to database.

If you have admin permissions on the script and open the tablet using item you will still have a limited access to it, if you want the full access you must use /tablet.

API

API exports functions and events (client side):

openTablet(fullAccess) / openMinimal(fullAccess)

Opens tablet or minimal UI.

Paremeters:

client.lua
-- TABLET UI
-- Full Access
exports['sb-handlingtuning']:openTablet(true)

-- Limited Access
exports['sb-handlingtuning']:openTablet(false)

-- MINIMAL UI
-- Full Access
exports['sb-handlingtuning']:openMinimal(true)

-- Limited Access
exports['sb-handlingtuning']:openMinimal(false)

setDriftMode(toggle)

Sets Drift Mode either enabled or disabled.

Parameters:

  • toggle - boolean(true/false) Enable disable the drift mode of a vehicle player is currently sitting in.

client.lua
-- Enable
exports['sb-handlingtuning']:setDriftMode(true)

-- Disable
exports['sb-handlingtuning']:setDriftMode(false)

setVehicleHandlingValue(key, value, vehicle)

Use instead of natives for vehicle handling (SetVehicleHandlingField, SetVehicleHandlingFloat, SetVehicleHandlingInt, SetVehicleHandlingVector). If you have any script that uses these natives replace them with this export.

Parameters:

  • key - string vehicle handling field (e.g nInitialDriveGears, fInitialDriveForce);

  • value - number value for field to set;

  • vehicle - vehicle handler (optional, default vehicle player is in).

Example to replace in other script:

client.lua
--SetVehicleHandlingFloat(currentVehicle, "CHandlingData", "fClutchChangeRateScaleDownShift", 0.0)
exports['sb-handlingtuning']:setVehicleHandlingValue('fClutchChangeRateScaleDownShift', 0.0, currentVehicle)

resetHandling()

Resets handling to standard vehicle values.

client.lua
exports['sb-handlingtuning']:resetHandling()

SetFrontCamber(vehicle, value) / SetRearCamber(vehicle, value)

Sets vehicle front / rear camber for stance.

client.lua
exports['sb-handlingtuning']:SetFrontCamber() -- Sets front Camber
exports['sb-handlingtuning']:SetRearCamber() -- Sets rear Camber

SetFrontWheelOffset(vehicle, value) / SetRearWheelsOffset(vehicle, value)

Sets vehicle front / rear wheels offset for stance.

client.lua
exports['sb-handlingtuning']:SetFrontWheelOffset() -- Sets fron wheels ofsset
exports['sb-handlingtuning']:SetRearWheelsOffset() -- Sets rear wheels offset

Common Issues / FAQ

Why I can not see all options?

You probably are using tablet with limited access. In Config.Groups you can set that for example Engine group would require engine level 4 upgrade installed on the vehicle. So you either want to install all the upgrades or open tablet using /tablet command. See more information in https://github.com/daZepelin/sb-handlingtuning/blob/gitbook/docs/handling-tuning.md#how-to-use

Why I can not toggle Drift Mode?

See https://github.com/daZepelin/sb-handlingtuning/blob/gitbook/docs/handling-tuning.md#why-i-can-not-see-all-options.

I do not use any framework, will handling system work on my server?

Yes, the system has build in options to work without any framework and any other scripts. To make it work you would need to set Config.Framework and Config.NotificationSystem to 'custom'. The framework implementation only allows owned vehicles to save their handlings.

I change handling values, but they make no effect, when I reload tablet they get back to default

This most likely happens because you have some other script that changes handling values and interrupts sb-handlingtuning functionality. Make sure you do not have any other handling editors, tuning tablets or engine swap scripts installed in your server. Mostly often it is qb-vehiclefailure or fivem-realisticvehicle resources that affect braking force.

Changelog

v1.0.0.3

  • Fixed some of database issues and loading on esx and mysql-async scritpts;

  • Fixed pressing E and Q fading in the minimal UI even if the tablet UI is on;

  • Fixed some UI errors.

v1.0.1 - v1.0.1.2

  • Fixes on key presses causing UI errors;

  • Created and added more errors handlers for easier debugging;

  • Fixed some sql queries to work with older mysql-async versions;

  • Fixed issue that caused break on saving presets and generating xml files;

  • Adjusted the way standard vehicles are being loaded. Now it might take longer, but will more likely not break and get stuck.

v1.0.1.3

v1.0.2

  • Changed json to longtext in sql queries, as for some db versions it was causing issues;

  • Fixed issue where drift mode values were resetting when not intended;

  • Added missing handling fields, that had their groups missing;

  • Drift group values were saving some not needed values to standard values;

  • Added tablet command name config;

  • Added api for setting handling values, now the system will be easier to implement to other of your systems.

v1.0.3

  • Added wheels stancer tuning to the tablet. You can adjust wheels base width and camber. For now this is only synced with players inside the car. Also created api for that;

  • Added drifting heat. If drift mode is on this will reduce the tires grip after drifting and will gradually get back to normal grip if not drifting anymore. This should help initiate next slide after being in drift;

  • Fixed tablet icons and property description element;

  • Fixed some issues with drift mode, which was not activating in some cases.

Was this helpful?