> For the complete documentation index, see [llms.txt](https://docs.vames-store.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vames-store.com/assets/vms_multichars/configuration-files/config.client.lua.md).

# config.client.lua

Preview File Updated: v2.0.0 - 22.08.2026

```lua
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, 'fa-solid fa-users')
    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.Hud = {
    Enable = function()
        if GetResourceState('vms_hud') ~= 'missing' then
            exports['vms_hud']:Display(true)
        end
    end,
    Disable = function()
        if GetResourceState('vms_hud') ~= 'missing' then
            exports['vms_hud']:Display(false)
            DisplayRadar(false)
        end
    end
}


-- ████████╗ █████╗ ██████╗  ██████╗ ███████╗████████╗
-- ╚══██╔══╝██╔══██╗██╔══██╗██╔════╝ ██╔════╝╚══██╔══╝
--    ██║   ███████║██████╔╝██║  ███╗█████╗     ██║   
--    ██║   ██╔══██║██╔══██╗██║   ██║██╔══╝     ██║   
--    ██║   ██║  ██║██║  ██║╚██████╔╝███████╗   ██║   
--    ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝ ╚══════╝   ╚═╝   
CL.Target = function(action, data)
    if action == 'zone' 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
                    options[#options + 1] = {
                        name = v.name,
                        icon = v.icon,
                        label = v.label,
                        onSelect = v.action,
                        canInteract = v.canInteract,
                        distance = v.distance or 1.2,
                        items = v.requiredItem,
                        groups = v.jobs,
                    }
                end
            end

            return exports['ox_target']:addBoxZone({
                coords = vec(data.coords.x, data.coords.y, data.coords.z-0.5),
                size = data.size,
                debug = Config.DebugTarget,
                useZ = true,
                rotation = data.rotation or 0.0,
                options = options
            })
        elseif Config.TargetResource == 'qb-target' then
            local uniqueName = 'vms_multichars-'..math.random(1000000, 9999999999)
            local options = {}

            if data.options and next(data.options) then
                for k, v in pairs(data.options) do
                    local id = #options + 1
                    options[id] = {
                        num = id,
                        icon = v.icon,
                        label = v.label,
                        action = v.action,
                        canInteract = v.canInteract,
                        distance = v.distance or 1.2,
                        item = v.requiredItem,
                        job = v.jobs,
                    }
                    if v.jobs and type(v.jobs) == 'table' then
                        options[id].job = {}
                        for _, job in ipairs(v.jobs) do
                            options[id].job[job] = 0
                        end
                    end
                end
            end

            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.rotation and data.rotation - 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 = options,
                    distance = 3.5,
                }
            )

            return uniqueName
        else
            warn('You need to prepare CL.Target for the target system')
        end
        
    elseif action == '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
    end
end


-- ████████╗███████╗██╗  ██╗████████╗██╗   ██╗██╗
-- ╚══██╔══╝██╔════╝╚██╗██╔╝╚══██╔══╝██║   ██║██║
--    ██║   █████╗   ╚███╔╝    ██║   ██║   ██║██║
--    ██║   ██╔══╝   ██╔██╗    ██║   ██║   ██║██║
--    ██║   ███████╗██╔╝ ██╗   ██║   ╚██████╔╝██║
--    ╚═╝   ╚══════╝╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝
CL.TextUI = {
    Open = function(text)
        if Config.TextUI == 'vms_notifyv2' then
            text = '~INPUT_CONTEXT~ ' .. text
            exports['vms_notifyv2']:ShowTextUI(text)
            exports['vms_notifyv2']:UpdateTextUI(text)
        elseif Config.TextUI == 'qb-core' then
            text = '[E] ' .. text
            exports['qb-core']:DrawText(text, 'left')
        elseif Config.TextUI == 'lation_ui' then
            exports.lation_ui:showText({
                description = text,
                keybind = 'E',
            })
        elseif Config.TextUI == 'wasabi_uikit' then
            exports.wasabi_uikit:OpenTextUI(text, 'E', 'right', 'normal')
        elseif Config.TextUI == 'ox_lib' then
            text = '[E] ' .. text
            exports.ox_lib:showTextUI(text)
        end
    end,
    Close = function()
        if Config.TextUI == 'vms_notifyv2' then
            exports['vms_notifyv2']:HideTextUI()
        elseif Config.TextUI == 'qb-core' then
            exports['qb-core']:HideText()
        elseif Config.TextUI == 'lation_ui' then
            exports.lation_ui:hideText()
        elseif Config.TextUI == 'wasabi_uikit' then
            exports.wasabi_uikit:CloseTextUI()
        elseif Config.TextUI == 'ox_lib' then
            exports.ox_lib:hideTextUI()
        end
    end
}


if Config.RelogCommand then
	RegisterCommand('relog', function()
		if CanRelog == true then
			CanRelog = false
			TriggerServerEvent('vms_multichars:relog')

			SetTimeout(10000, function()
				CanRelog = true
			end)
		end
	end)
end
```
