config.client.lua
Preview File Updated: v1.0.2 - 04/08/2026
CL = {}
-- ███╗ ██╗ ██████╗ ████████╗██╗███████╗██╗ ██████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗███████╗
-- ████╗ ██║██╔═══██╗╚══██╔══╝██║██╔════╝██║██╔════╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
-- ██╔██╗ ██║██║ ██║ ██║ ██║█████╗ ██║██║ ███████║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
-- ██║╚██╗██║██║ ██║ ██║ ██║██╔══╝ ██║██║ ██╔══██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
-- ██║ ╚████║╚██████╔╝ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║███████║
-- ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
CL.Notification = function(data)
local color =
data.type == "success" and '#36f230' or
data.type == "error" and '#f23030' or
data.type == "info" and '#4287f5'
if GetResourceState("vms_notify") == 'started' then
exports['vms_notify']:Notification("", data.message, data.time, color, data.icon)
elseif GetResourceState("lation_ui") == 'started' then
exports['lation_ui']:notify({
message = data.message,
type = data.type,
duration = data.time,
})
else
TriggerEvent('esx:showNotification', data.message)
TriggerEvent('QBCore:Notify', data.message, 'primary', data.time)
end
end
CL.QuestionMenu = function(data, cb)
if GetResourceState("vms_notifyv2") == 'started' then
local question = exports['vms_notifyv2']:Question({
title = data.title,
description = data.description,
color = "#673feb",
icon = "fa-solid fa-circle-question",
}, {
{
displayKey = "Y",
description = TRANSLATE("control.request:accept"),
control = 246
},
{
displayKey = "N",
description = TRANSLATE("control.request:decline"),
control = 306
}
})
Citizen.Await(question) -- IT MUST BE HERE
if question == "246" then -- export returns clicked control as string!
cb(true)
else
cb(false)
end
elseif GetResourceState('lation_ui') == 'started' then
local result = exports.lation_ui:alert({
header = data.title,
content = data.description,
icon = 'fa-solid fa-circle-question',
iconColor = '#673feb',
type = 'default',
labels = {
cancel = TRANSLATE("control.request:decline"),
confirm = TRANSLATE("control.request:accept"),
}
})
if result == 'confirm' then
cb(true)
else
cb(false)
end
end
end
-- ████████╗ █████╗ ██████╗ ██████╗ ███████╗████████╗
-- ╚══██╔══╝██╔══██╗██╔══██╗██╔════╝ ██╔════╝╚══██╔══╝
-- ██║ ███████║██████╔╝██║ ███╗█████╗ ██║
-- ██║ ██╔══██║██╔══██╗██║ ██║██╔══╝ ██║
-- ██║ ██║ ██║██║ ██║╚██████╔╝███████╗ ██║
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝
CL.Target = function(type, data)
if type == 'entity' then
if Config.TargetResource == 'ox_target' then
local options = {}
if data.options and next(data.options) then
for k, v in pairs(data.options) do
local icon = v.icon or 'fa-solid fa-bars' -- Default Icon
options[#options + 1] = {
name = v.name,
icon = icon,
label = v.label,
distance = v.distance or 1.2,
items = v.requiredItem,
groups = v.jobs,
onSelect = v.action,
canInteract = v.canInteract,
}
end
end
exports['ox_target']:addLocalEntity(data.entity, options)
elseif Config.TargetResource == 'qb-target' then
local options = {}
if data.options and next(data.options) then
for k, v in pairs(data.options) do
local icon = v.icon or 'fa-solid fa-bars' -- Default Icon
options[#options + 1] = {
num = #options + 1,
icon = icon,
label = v.label,
distance = v.distance or 1.2,
item = v.requiredItem,
job = v.jobs,
action = v.action,
canInteract = v.canInteract,
}
end
end
exports['qb-target']:AddTargetEntity(data.entity, {
options = options,
distance = 2.0
})
else
warn('You need to prepare CL.Target for the target system')
end
elseif type == 'remove-entity' then
if Config.TargetResource == 'ox_target' then
exports['ox_target']:removeLocalEntity(data)
elseif Config.TargetResource == 'qb-target' then
exports['qb-target']:RemoveTargetEntity(data)
else
warn('You need to prepare CL.Target for the target system')
end
end
end
-- ██████╗ ██████╗ ████████╗███████╗██╗ ██╗████████╗
-- ╚════██╗██╔══██╗ ╚══██╔══╝██╔════╝╚██╗██╔╝╚══██╔══╝
-- █████╔╝██║ ██║ ██║ █████╗ ╚███╔╝ ██║
-- ╚═══██╗██║ ██║ ██║ ██╔══╝ ██╔██╗ ██║
-- ██████╔╝██████╔╝ ██║ ███████╗██╔╝ ██╗ ██║
-- ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝
CL.DrawText3D = function(coords, text)
if not Config.UseDrawText then return end
local textScale = 0.50
local camCoords = GetFinalRenderedCamCoord()
local distance = #(coords.xyz - camCoords)
local scale = (textScale / distance) * 2
local fov = (1 / GetGameplayCamFov()) * 100
scale = scale * fov
SetTextScale(0.0 * scale, 0.50 * scale)
SetTextFont(4)
SetTextDropshadow(0, 0, 0, 0, 255)
SetTextProportional(1)
SetTextColour(255, 255, 255, 205)
SetTextDropShadow()
SetTextCentre(true)
if Config.UseDrawTextBox then
BeginTextCommandWidth("STRING")
AddTextComponentString(text)
local textWidth = EndTextCommandGetWidth(true) + (0.006 * scale * 2)
SetDrawOrigin(coords.x, coords.y, coords.z, 0)
DrawRect(0.0, 0.018 * scale, textWidth, 0.045 * scale, 11, 4, 20, 120)
else
SetDrawOrigin(coords.x, coords.y, coords.z, 0)
end
SetTextEntry("STRING")
AddTextComponentString(text)
DrawText(0.0, 0.0)
ClearDrawOrigin()
end
-- ███████╗██████╗ █████╗ ███╗ ███╗███████╗██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗
-- ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝
-- █████╗ ██████╔╝███████║██╔████╔██║█████╗ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝
-- ██╔══╝ ██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝ ██║███╗██║██║ ██║██╔══██╗██╔═██╗
-- ██║ ██║ ██║██║ ██║██║ ╚═╝ ██║███████╗╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
CL.IsPlayerLoaded = function(type)
if Config.Core == "ESX" then
return ESX.IsPlayerLoaded()
elseif Config.Core == "QB-Core" then
return CL.GetPlayerData() and CL.GetPlayerData().job ~= nil
end
end
CL.GetPlayerData = function(type)
if Config.Core == "ESX" then
return ESX.GetPlayerData()
elseif Config.Core == "QB-Core" then
return QBCore.Functions.GetPlayerData()
end
end
CL.GetItemLabel = function(name)
if GetItemLabel then
return GetItemLabel(name)
else
if Config.Core == "QB-Core" and QBCore?.Shared?.Items then
local item = QBCore.Shared.Items[name]
if item.label then
return item.label
end
end
return name
end
end
CL.GetCancelUsageAction = function(ped)
-- Death Check
if GetEntityHealth(ped) <= 0 or IsEntityDead(ped) or LocalPlayer.state.isDead then
return 'drop'
end
-- Stun Check
if IsPedBeingStunned(ped) then
return 'drop'
end
-- Ragdoll
local ragdollReason = DetectRagdollReason(ped)
if ragdollReason == 'fall' or ragdollReason == 'vehicleHit' then
return 'drop'
end
-- qb-smallresources handsup.lua
-- if exports['qb-smallresources']:getHandsup() then
-- return 'cancel'
-- end
-- Example: Handcuffed
-- if exports['your_cuffs']:IsHandcuffed() then
-- return 'cancel'
-- end
return false
end
CL.GetPlayerGender = function(ped)
local model = GetEntityModel(ped)
if model == GetHashKey("mp_m_freemode_01") then
return "male"
elseif model == GetHashKey("mp_f_freemode_01") then
return "female"
end
return "unknown"
end
-- ███████╗████████╗ █████╗ ████████╗██╗ ██╗███████╗
-- ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██║ ██║██╔════╝
-- ███████╗ ██║ ███████║ ██║ ██║ ██║███████╗
-- ╚════██║ ██║ ██╔══██║ ██║ ██║ ██║╚════██║
-- ███████║ ██║ ██║ ██║ ██║ ╚██████╔╝███████║
-- ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
CL.OnConsume = function(itemName, biteSize)
local isGymStarted = GetResourceState('vms_gym') == 'started'
if isGymStarted then
local value = ({
-- Here you can configure the items that will negatively affect the player's stamina.
['cigarette'] = math.random(1, 8), -- 0.1 - 0.8%
['joint_sd'] = math.random(0, 5), -- 0.0 - 0.5%
['joint_nl'] = math.random(0, 5), -- 0.0 - 0.5%
})[itemName]
if value and value >= 1 then
value = value / 10
exports["vms_gym"]:removeSkill('condition', value)
end
end
end
CreateThread(function()
while WaitingForLoad do
Citizen.Wait(100)
end
local resourceName = GetCurrentResourceName()
while true do
Wait(2000)
if CL.IsPlayerLoaded() then
local removeHealth = 0
local hunger = exports[resourceName]:GetPercentageStatus('hunger')
local thirst = exports[resourceName]:GetPercentageStatus('thirst')
if hunger <= 5 then
removeHealth = removeHealth + math.random(0, 2)
end
if thirst <= 5 then
removeHealth = removeHealth + math.random(0, 3)
end
if removeHealth > 0 then
local myPed = PlayerPedId()
local health = GetEntityHealth(myPed)
SetEntityHealth(myPed, health - removeHealth)
end
end
end
end)
-- ██╗███╗ ██╗██╗████████╗██╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗
-- ██║████╗ ██║██║╚══██╔══╝██║██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║
-- ██║██╔██╗ ██║██║ ██║ ██║███████║ ██║ ██║██║ ██║██╔██╗ ██║
-- ██║██║╚██╗██║██║ ██║ ██║██╔══██║ ██║ ██║██║ ██║██║╚██╗██║
-- ██║██║ ╚████║██║ ██║ ██║██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║
-- ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
function CL.InitiateFunctions()
-- Ambulance Integration
local function RestoreDefaultStatuses()
local hunger = exports['vms_needs']:GetPercentageStatus('hunger')
if hunger < 50.0 then
exports['vms_needs']:SetStatus('hunger', 250.0) -- 250.0 = half
end
local thirst = exports['vms_needs']:GetPercentageStatus('thirst')
if thirst < 50.0 then
exports['vms_needs']:SetStatus('thirst', 250.0) -- 250.0 = half
end
end
local foundIntegration = false
if GetResourceState('tk_ambulancejob') == 'started' then
foundIntegration = 'tk_ambulancejob'
RegisterNetEvent('tk_ambulancejob:onPlayerRevive', function()
RestoreDefaultStatuses()
exports['vms_needs']:CleanupOptionalStatuses()
end)
elseif GetResourceState('wasabi_ambulance') == 'started' then
foundIntegration = 'wasabi_ambulance'
RegisterNetEvent('wasabi_ambulance:revive', function()
Citizen.Wait(500) -- Wait for the player to be fully revived
exports['vms_needs']:ReloadVisualEffect()
end)
RegisterNetEvent('wasabi_ambulance:revivePlayer', function()
Citizen.Wait(500) -- Wait for the player to be fully revived
exports['vms_needs']:ReloadVisualEffect()
end)
elseif GetResourceState('wasabi_ambulance_v2') == 'started' then
foundIntegration = 'wasabi_ambulance_v2'
RegisterNetEvent('wasabi_ambulance:Client:OnRevive', function()
Citizen.Wait(500) -- Wait for the player to be fully revived
exports['vms_needs']:ReloadVisualEffect()
end)
RegisterNetEvent('wasabi_ambulance:Client:Listeners:OnRespawn', function()
exports['vms_needs']:CleanupOptionalStatuses()
end)
RegisterNetEvent('wasabi_ambulance:Client:Listeners:OnFacilityHeal', function()
exports['vms_needs']:CleanupOptionalStatuses()
end)
end
if foundIntegration then
library.Debug(('^2[Integration]^7 Found Ambulance Integration: ^3%s^7'):format(foundIntegration))
end
end
Last updated