local isOpen = false -- whether the custom pause/NUI is open
local tabletModel = `prop_cs_tablet`-- prop to attach while the menu is open
local tabletEntity = nil -- handle to the created tablet object
-- Safe Config fallback
Config = Config or {}
--------------------------------------------------------------
-- Helpers: Animation + Prop attach for nice opening effect --
--------------------------------------------------------------
local function ensureAnimDict(dict)
if not HasAnimDictLoaded(dict) then
RequestAnimDict(dict)
end
while not HasAnimDictLoaded(dict) do
Wait(0)
end
end
local function startTabletScene()
ensureAnimDict('amb@code_human_in_bus_passenger_idles@female@tablet@idle_a')
local ped = PlayerPedId()
-- Create tablet prop if not already spawned
if not DoesEntityExist(tabletEntity) then
tabletEntity = CreateObject(tabletModel, 0.0, 0.0, 0.0, true, true, true)
-- Attach to right hand
AttachEntityToEntity(tabletEntity, ped, GetPedBoneIndex(ped, 28422), 0.0, 0.0, 0.0, 10.0, 160.0, 0.0, true, true, false, true, 1, true)
end
-- Play looping idle anim holding the tablet
TaskPlayAnim(ped, 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a', 'idle_a', 2.0, 3.0, -1, 51, 0.0, false, false, false)
end
local function stopTabletScene()
if tabletEntity then
DeleteEntity(tabletEntity)
tabletEntity = nil
end
ClearPedTasks(PlayerPedId())
end
--------------------------------------------------------------
-- NUI helpers
--------------------------------------------------------------
local function nuiPost(message) -- Send message to UI
SendNUIMessage(message)
end
local function openMenu()
if IsPauseMenuActive() or IsNuiFocused() then
return
end
isOpen = true
SetNuiFocus(true, true)
startTabletScene()
-- Prime UI with language + config + static label set
nuiPost({
type = 'show',
show = true,
config = Config,
lang = Lang and Lang.getNui and ({ Lang.getNui() })[1] or {},
})
-- Also push immediate player snapshot (so UI has something on first draw)
local function pushSnapshot()
local Player = exports['cq-lib']

layer()
if not Player.isLoad() then
return
end
local data = {}
data.player = Player.GetInfo()
data.job = Player.GetJob()
data.accounts = Player.GetMoney() or {}
data.skill = (Player.GetSkill and Player.GetSkill()) or { level = 0, exp = 0 }
-- optional dependencies
if GetResourceState('cq-bills') == 'started' then
data.bills = exports['cq-bills']:GetPlayerBills() or {}
end
if exports['cq-lib'].GetBusiness then
data.business = exports['cq-lib']:GetBusiness() or {}
end
if exports['cq-lib'].GetProperties then
data.properties = exports['cq-lib']:GetProperties() or {}
end
-- discord avatar (fallback image if missing)
local avatar = (exports['cq-lib'].getDiscordProfile and exports['cq-lib']:getDiscordProfile() or {}).avatar
data.user_img = avatar or '
https://r2.fivemanage.com/u5HR6uOgjbQM4owiGySU1/isologo-CodeIQ.png'
-- Useful strings
if data.player and data.player.firstname and data.player.lastname then
data.name = (data.player.firstname or '') .. ' ' .. (data.player.lastname or '')
end
-- normalize accounts
data.cash = (data.accounts and data.accounts.cash) or 0
data.bank = (data.accounts and data.accounts.bank) or 0
data.crypto = (data.accounts and data.accounts.crypto) or 0
nuiPost({ type = 'update', data = data })
end
-- push once now
pushSnapshot()
-- spawn background thread to keep UI refreshed while open
CreateThread(function()
while isOpen do
local interval = 2000
local Player = exports['cq-lib']

layer()
if not Player.isLoad() then
interval = 1000
else
pushSnapshot()
end
Wait(interval)
end
end)
end
local function closeMenu()
isOpen = false
SetNuiFocus(false, false)
nuiPost({ type = 'show', show = false })
stopTabletScene()
end
--------------------------------------------------------------
-- Commands and key mapping (fully open & editable) --
--------------------------------------------------------------
RegisterCommand((Config.keymap and Config.keymap.command) or 'pause', function()
if IsPauseMenuActive() or IsNuiFocused() then return end
openMenu()
end, false)
-- Default ESC key; change in Config.keymap if needed
RegisterKeyMapping(
(Config.keymap and Config.keymap.command) or 'pause',
(Config.keymap and Config.keymap.description) or 'Open Settings Menu',
(Config.keymap and Config.keymap.device) or 'keyboard',
(Config.keymap and Config.keymap.default_key) or 'ESCAPE'
)
--------------------------------------------------------------
-- NUI Callbacks --
--------------------------------------------------------------
-- Fetch translations from runtime Lang (cq-lib locale helper)
RegisterNUICallback('GetLang', function(_, cb)
if Lang and Lang.getNui then
local ok, phrases = pcall(Lang.getNui, Lang)
if ok then
cb(phrases)
return
end
end
cb({}) -- fallback empty
end)
-- Hide/close UI from inside NUI
RegisterNUICallback('hideUI', function(_, cb)
closeMenu()
cb('ok')
end)
-- Left bar actions (map, settings, help, etc.)
RegisterNUICallback('LeftBar', function(data, cb)
local action = data and data.action
if action == 'map' then
ActivateFrontendMenu(GetHashKey('FE_MENU_VERSION_MP_PAUSE'), false, -1)
elseif action == 'settings' then
ActivateFrontendMenu(GetHashKey('FE_MENU_VERSION_LANDING_MENU'), false, -1)
elseif action == 'hideUI' then
closeMenu()
elseif action == 'help' then
closeMenu()
if exports['cq-lib'].HelpMenu then exports['cq-lib']:HelpMenu() end
elseif action == 'support' then
closeMenu()
if exports['cq-lib'].SupportMenu then exports['cq-lib']:SupportMenu() end
elseif action == 'disconnect' then
closeMenu()
if exports['cq-lib'].DropPlayer then exports['cq-lib']

ropPlayer() end
elseif action == 'logout' then
closeMenu()
if exports['cq-lib'].LogoutEvent then exports['cq-lib']:LogoutEvent() end
end
cb('ok')
end)
-- Shortcut buttons call into cq-lib exports by name (if present)
RegisterNUICallback('Shortcuts', function(data, cb)
local action = data and data.action
if action and exports['cq-lib'][action] then
exports['cq-lib'][action](exports['cq-lib'])
end
cb('ok')
end)
--------------------------------------------------------------
-- Disable default GTA pause menu while our UI is open --
--------------------------------------------------------------
CreateThread(function()
while true do
Wait(1)
SetPauseMenuActive(false)
end
end)