Full View config.client.lua
Preview File Updated: v2.0.9 - 09.01.2025
if Config.Core == "ESX" then
RegisterNetEvent(Config.PlayerSetJob)
AddEventHandler(Config.PlayerSetJob, function(PLAYER_JOB)
PlayerData.job = PLAYER_JOB
end)
elseif Config.Core == "QB-Core" then
RegisterNetEvent(Config.PlayerSetJob)
AddEventHandler(Config.PlayerSetJob, function(PLAYER_JOB)
PlayerData.job = PLAYER_JOB
end)
end
function DrawText3D(x, y, z, text) -- This is the function used when using Config.Use3DText
SetTextScale(0.45, 0.45)
SetTextFont(4)
SetTextDropShadow()
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry("STRING")
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
ClearDrawOrigin()
end
CL = {}
CL.AllowOpenTuningMenu = function(ped, vehicle)
--[[
In this function, you can enter your dependencies to run the tuning menu
If the player is not to be able to run the menu,
you must make return false, otherwise return true
EXAMPLE:
if not vehicle then
return Config.Notification("You cannot run the menu...", 4000, 'error')
end
]]
return true
end
-- ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗███████╗███████╗ ██████╗ █████╗ ██████╗
-- ██╔══██╗██╔══██╗██╔═══██╗██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔════╝ ██╔══██╗██╔══██╗██╔══██╗
-- ██████╔╝██████╔╝██║ ██║██║ ███╗██████╔╝█████╗ ███████╗███████╗ ██████╔╝███████║██████╔╝
-- ██╔═══╝ ██╔══██╗██║ ██║██║ ██║██╔══██╗██╔══╝ ╚════██║╚════██║ ██╔══██╗██╔══██║██╔══██╗
-- ██║ ██║ ██║╚██████╔╝╚██████╔╝██║ ██║███████╗███████║███████║ ██████╔╝██║ ██║██║ ██║
-- ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
CL.ProgressBar = function(label, time)
exports['progressbar']:Progress({
name = 'installation',
label = label,
duration = time,
canCancel = false,
controlDisables = {
disableMouse = false,
disableMovement = true,
disableCarMovement = true,
disableCombat = true,
}
})
end
-- ███████╗██╗ ██╗██╗██╗ ██╗ ██████╗ █████╗ ██████╗
-- ██╔════╝██║ ██╔╝██║██║ ██║ ██╔══██╗██╔══██╗██╔══██╗
-- ███████╗█████╔╝ ██║██║ ██║ ██████╔╝███████║██████╔╝
-- ╚════██║██╔═██╗ ██║██║ ██║ ██╔══██╗██╔══██║██╔══██╗
-- ███████║██║ ██╗██║███████╗███████╗ ██████╔╝██║ ██║██║ ██║
-- ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
CL.Skillbar = function(cb)
local finished = exports["tgiann-skillbar"]:taskBar(3000)
cb(finished)
end
-- ████████╗ █████╗ ██████╗ ██████╗ ███████╗████████╗
-- ╚══██╔══╝██╔══██╗██╔══██╗██╔════╝ ██╔════╝╚══██╔══╝
-- ██║ ███████║██████╔╝██║ ███╗█████╗ ██║
-- ██║ ██╔══██║██╔══██╗██║ ██║██╔══╝ ██║
-- ██║ ██║ ██║██║ ██║╚██████╔╝███████╗ ██║
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝
CL.Target = function(type, data, cb)
if type == 'part' then
if Config.TargetResource == 'ox_target' then
return exports['ox_target']:addBoxZone({
coords = vec(data.coords.x, data.coords.y, data.coords.z-0.5),
size = data.size and data.size.xyz or vec(1.2, 1.2, 1.8),
debug = false,
useZ = true,
rotation = data.vehicleHeading or 0.0,
options = {
{
name = 'tuning-part',
icon = data.icon,
label = data.label,
onSelect = function()
cb()
end,
distance = 1.2,
}
}
})
elseif Config.TargetResource == 'qb-target' then
local uniqueName = 'vms_tuning-'..math.random(1000000, 9999999999)
exports['qb-target']:AddBoxZone(uniqueName, vec(data.coords.x, data.coords.y, data.coords.z), data.size and data.size.x or 1.2, data.size and data.size.y or 1.2, {
name = uniqueName,
heading = data.vehicleHeading and data.vehicleHeading - 90.0 or 0.0,
debugPoly = false,
minZ = data.coords.z - (data.size and data.size.y or 1.2),
maxZ = data.coords.z + (data.size and data.size.y or 1.2),
}, {
options = {
{
num = 1,
icon = data.icon,
label = data.label,
action = function()
cb()
end,
}
},
distance = 1.2,
})
return uniqueName
else
warn('You need to prepare CL.Target for the target system')
end
elseif type == 'remove-zone' then
if Config.TargetResource == 'ox_target' then
exports['ox_target']:removeZone(data)
elseif Config.TargetResource == 'qb-target' then
exports['qb-target']:RemoveZone(data)
else
warn('You need to prepare CL.Target for the target system')
end
else
if Config.TargetResource == 'ox_target' then
exports['ox_target']:addBoxZone({
coords = vec(data.coords.x, data.coords.y, data.coords.z-0.5),
size = vec(1.8, 1.8, 1.8),
debug = false,
useZ = true,
rotation = 0.0,
distance = 1.2,
options = {
{
name = 'tuning-bossmenu',
icon = data.icon,
label = data.label,
groups = data.job,
onSelect = function()
cb()
end,
canInteract = data.canInteract
}
}
})
elseif Config.TargetResource == 'qb-target' then
local uniqueName = 'tuning-bossmenu-'..math.random(1000000, 9999999999)
exports['qb-target']:AddBoxZone(uniqueName, vec(data.coords.x, data.coords.y, data.coords.z), 1.8, 1.8, {
name = uniqueName,
heading = 0.0,
debugPoly = false,
minZ = data.coords.z - 1.8,
maxZ = data.coords.z + 1.8,
}, {
options = {
{
num = 1,
icon = data.icon,
label = data.label,
job = data.job,
action = function()
cb()
end,
canInteract = data.canInteract
}
},
distance = 1.2,
})
else
warn('You need to prepare CL.Target for the target system')
end
end
end
-- ███████╗ ██████╗ ██╗ ██╗███╗ ██╗██████╗ ███████╗███████╗███████╗███████╗ ██████╗████████╗███████╗
-- ██╔════╝██╔═══██╗██║ ██║████╗ ██║██╔══██╗ ██╔════╝██╔════╝██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝
-- ███████╗██║ ██║██║ ██║██╔██╗ ██║██║ ██║ █████╗ █████╗ █████╗ █████╗ ██║ ██║ ███████╗
-- ╚════██║██║ ██║██║ ██║██║╚██╗██║██║ ██║ ██╔══╝ ██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ╚════██║
-- ███████║╚██████╔╝╚██████╔╝██║ ╚████║██████╔╝ ███████╗██║ ██║ ███████╗╚██████╗ ██║ ███████║
-- ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝
CL.PlayInstallationSoundEffect = function(part, fileName)
if not Config.UseInstallationSoundEffects then;return;end;
if not Config.PartsInstallationSoundEffects[part] then;return;end;
if not Config.PartsInstallationSoundEffects[part].use then;return;end;
local xsound = GetResourceState('xsound') == 'started'
local mx_surround = GetResourceState('mx-surround') == 'started'
local interactSound = GetResourceState('InteractSound') == 'started' or GetResourceState('interactSound') == 'started' or GetResourceState('interact-sound') == 'started'
if xsound or mx_surround or interactSound then
TriggerServerEvent('InteractSound_SV:PlayWithinDistance', 4.0, Config.PartsInstallationSoundEffects[part].fileName, Config.PartsInstallationSoundEffects[part].volume)
end
end
-- ██████╗ ██╗ ██╗███████╗███████╗████████╗██╗ ██████╗ ███╗ ██╗ ███╗ ███╗███████╗███╗ ██╗██╗ ██╗
-- ██╔═══██╗██║ ██║██╔════╝██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║ ████╗ ████║██╔════╝████╗ ██║██║ ██║
-- ██║ ██║██║ ██║█████╗ ███████╗ ██║ ██║██║ ██║██╔██╗ ██║ ██╔████╔██║█████╗ ██╔██╗ ██║██║ ██║
-- ██║▄▄ ██║██║ ██║██╔══╝ ╚════██║ ██║ ██║██║ ██║██║╚██╗██║ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║██║ ██║
-- ╚██████╔╝╚██████╔╝███████╗███████║ ██║ ██║╚██████╔╝██║ ╚████║ ██║ ╚═╝ ██║███████╗██║ ╚████║╚██████╔╝
-- ╚══▀▀═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═════╝
CL.CustomQuestionMenu = function(requesterId, cache)
local question = exports['vms_notify']:Question(
"PARTS INSTALLATION REQUEST",
("Do you want to accept a request to install parts for a vehicle from player %s"):format(requesterId),
'#4287f5',
'fa-solid fa-screwdriver-wrench'
)
Citizen.Await(question)
if question == 'y' then -- vms_notify question export return 'y' when player accept and 'n' when player reject
TriggerServerEvent("vms_tuning:acceptTuneRequest", requesterId, cache)
else
TriggerServerEvent("vms_tuning:rejectTuneRequest", requesterId)
end
end
-- ███████╗██████╗ █████╗ ███╗ ███╗███████╗██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗
-- ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝
-- █████╗ ██████╔╝███████║██╔████╔██║█████╗ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝
-- ██╔══╝ ██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝ ██║███╗██║██║ ██║██╔══██╗██╔═██╗
-- ██║ ██║ ██║██║ ██║██║ ╚═╝ ██║███████╗╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
CL.GetClosestPlayer = function()
if Config.Core == "ESX" then
return ESX.Game.GetClosestPlayer(GetEntityCoords(PlayerPedId()), 6.0) -- ESX
elseif Config.Core == "QB-Core" then
return QBCore.Functions.GetClosestPlayer(GetEntityCoords(PlayerPedId())) -- QB-Core
end
end
CL.GetClosestPlayers = function()
if Config.Core == "ESX" then
local playerInArea = ESX.Game.GetPlayersInArea(GetEntityCoords(PlayerPedId()), 5.0)
return playerInArea
elseif Config.Core == "QB-Core" then
local playerInArea = QBCore.Functions.GetPlayersFromCoords(GetEntityCoords(PlayerPedId()), 5.0)
return playerInArea
end
end
CL.getPlayerJob = function(type)
if Config.Core == "ESX" then
if type == "table" and PlayerData.job then
return PlayerData.job
end
if type == "name" and PlayerData.job.name then
return PlayerData.job.name
end
if type == "grade_name" and PlayerData.job.grade_name then
return PlayerData.job.grade_name
end
elseif Config.Core == "QB-Core" then
if type == "table" and PlayerData.job then
return PlayerData.job
end
if type == "name" and PlayerData.job.name then
return PlayerData.job.name
end
if type == "grade_name" and PlayerData.job.grade.name then
return PlayerData.job.grade.name
end
end
return nil
end
CL.IsEmployee = function(jobName)
if Config.Core == "ESX" then
return PlayerData.job.name == jobName
elseif Config.Core == "QB-Core" then
return PlayerData.job.name == jobName
end
end
CL.IsManager = function(jobName, tuningId)
local managerGrades = Config.TuningPoints[tuningId].manager_grades
if Config.Core == "ESX" then
if PlayerData.job.name ~= jobName then
return false
end
if type(managerGrades) == 'table' then
for _, grade in ipairs(managerGrades) do
if PlayerData.job.grade_name == grade then
return true
end
end
else
return PlayerData.job.grade_name == managerGrades
end
elseif Config.Core == "QB-Core" then
if PlayerData.job.name ~= jobName then
return false
end
if type(managerGrades) == 'table' then
for _, grade in ipairs(managerGrades) do
if PlayerData.job.grade.name == grade then
return true
end
end
else
return PlayerData.job.grade.name == managerGrades
end
end
end
CL.IsBoss = function(jobName, tuningId)
local bossGrades = Config.TuningPoints[tuningId].boss_grades
if Config.Core == "ESX" then
if PlayerData.job.name ~= jobName then
return false
end
if type(bossGrades) == 'table' then
for _, grade in ipairs(bossGrades) do
if PlayerData.job.grade_name == grade then
return true
end
end
else
return PlayerData.job.grade_name == bossGrades
end
elseif Config.Core == "QB-Core" then
if PlayerData.job.name ~= jobName then
return false
end
if type(bossGrades) == 'table' then
for _, grade in ipairs(bossGrades) do
if PlayerData.job.grade.name == grade then
return true
end
end
else
return PlayerData.job.grade.name == bossGrades
end
end
end
CL.IsAllowedCityhall = function(jobName, tuningId)
local allowed = {}
local options = Config.TuningPoints[tuningId].cityhall_grades
if Config.Core == "ESX" then
if PlayerData.job.name ~= jobName then
return false
end
if options['resumes'] then
if type(options['resumes']) == 'table' then
for _, grade in ipairs(options['resumes']) do
if PlayerData.job.grade_name == grade then
allowed['resumes'] = true
break
end
end
else
if PlayerData.job.grade_name == options['resumes'] then
allowed['resumes'] = true
end
end
end
if options['taxes'] then
if type(options['taxes']) == 'table' then
for _, grade in ipairs(options['taxes']) do
if PlayerData.job.grade_name == grade then
allowed['taxes'] = true
break
end
end
else
if PlayerData.job.grade_name == options['taxes'] then
allowed['taxes'] = true
end
end
end
elseif Config.Core == "QB-Core" then
if PlayerData.job.name ~= jobName then
return false
end
if options['resumes'] then
if type(options['resumes']) == 'table' then
for _, grade in ipairs(options['resumes']) do
if PlayerData.job.grade.name == grade then
allowed['resumes'] = true
break
end
end
else
if PlayerData.job.grade.name == options['resumes'] then
allowed['resumes'] = true
end
end
end
if options['taxes'] then
if type(options['taxes']) == 'table' then
for _, grade in ipairs(options['taxes']) do
if PlayerData.job.grade.name == grade then
allowed['taxes'] = true
break
end
end
else
if PlayerData.job.grade.name == options['taxes'] then
allowed['taxes'] = true
end
end
end
end
return allowed
end
CL.IsPlayerOnDuty = function()
if Config.Core == "ESX" then
return true
elseif Config.Core == "QB-Core" then
return PlayerData.job.onduty
end
end
CL.GetEmployees = function(cb, jobName)
if Config.Core == "ESX" then
ESX.TriggerServerCallback('esx_society:getEmployees', function(employees)
cb(employees)
end, jobName)
-- local employees = lib.callback.await('esx_society:getEmployees', false, jobName) -- OX_LIB ESX_SOCIETY
-- cb(employees)
elseif Config.Core == "QB-Core" then
QBCore.Functions.TriggerCallback('qb-bossmenu:server:GetEmployees', function(employees)
cb(employees)
end, jobName)
end
end
CL.getVehiclePrice = function(vehicle, vehicleClass)
for model, price in pairs(Config.Vehicles) do
if GetEntityModel(vehicle) == GetHashKey(model) then
return price
end
end
if Config.VehiclesPricesByClass[vehicleClass] then
return Config.VehiclesPricesByClass[vehicleClass]
end
return nil
end
CL.UpdatedVehicle = function(vehicle, lastProperties, newProperties)
-- This function is executed only if the vehicle is present in the database and it has been tuned
if GetResourceState('AdvancedParking') ~= 'missing' then
exports["AdvancedParking"]:UpdateVehicle(vehicle)
end
end
-- ██╗ ██╗███████╗██╗ ██╗██╗ ██████╗██╗ ███████╗ ██╗ ██╗███████╗██╗ ██╗███████╗
-- ██║ ██║██╔════╝██║ ██║██║██╔════╝██║ ██╔════╝ ██║ ██╔╝██╔════╝╚██╗ ██╔╝██╔════╝
-- ██║ ██║█████╗ ███████║██║██║ ██║ █████╗ █████╔╝ █████╗ ╚████╔╝ ███████╗
-- ╚██╗ ██╔╝██╔══╝ ██╔══██║██║██║ ██║ ██╔══╝ ██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║
-- ╚████╔╝ ███████╗██║ ██║██║╚██████╗███████╗███████╗ ██║ ██╗███████╗ ██║ ███████║
-- ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝╚══════╝╚══════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝
CL.GiveVehicleKeys = function(vehicle, plate)
if GetResourceState('qs-vehiclekeys') ~= 'missing' then
local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
exports['qs-vehiclekeys']:GiveKeys(plate, model)
end
if GetResourceState('wasabi_carlock') ~= 'missing' then
exports['wasabi_carlock']:GiveKey(plate)
end
if GetResourceState('qb-vehiclekeys') ~= 'missing' then
TriggerEvent("vehiclekeys:client:SetOwner", plate)
end
end
CL.RemoveVehicleKeys = function(vehicle, plate)
if GetResourceState('qs-vehiclekeys') ~= 'missing' then
local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
exports['qs-vehiclekeys']:RemoveKeys(plate, model)
end
if GetResourceState('wasabi_carlock') ~= 'missing' then
exports['wasabi_carlock']:RemoveKey(plate)
end
if GetResourceState('qb-vehiclekeys') ~= 'missing' then
TriggerEvent("qb-vehiclekeys:client:RemoveKeys", plate)
end
end
-- █▄ ▄█ █ ▄▀▀ ▄▀▀ █ ▄▀▄ █▄ █ ▄▀▀
-- █ ▀ █ █ ▄██ ▄██ █ ▀▄▀ █ ▀█ ▄██
CL.OnMissionVehicle = function(vehicle)
-- OnMissionVehicle: the function is called on the NPC vehicle you will be repairing.
if GetResourceState('t1ger_keys') ~= 'missing' then
exports['t1ger_keys']:SetVehicleLocked(vehicle, 0)
end
end
Last updated