Skip to Content

Custom Framework - Client

Make sure to check the qb.lua and esx.lua files for examples on how to implement the phone for your framework. They are always up to date with the latest changes.

Framework check

At the top of the file, add a check for Config.Framework. If it’s not set to your framework, return to prevent it from loading.

if Config.Framework ~= "your-framework" then return end

Wait for player to load

Next, you need to wait for the player to load. How this is done depends on your framework. Once the player’s character has loaded, set loaded = true. This lets the phone know that your framework has loaded, and is ready to be used.

while not ESX.PlayerLoaded do Wait(500) end loaded = true

Framework events

The phone has a few common functions that can be used for framework events.

Player unload/switching character

Trigger LogOut() when the player unloads their character. This closes the phone, ends calls etc.

-- This is an example from the lb-phone qb.lua file RegisterNetEvent("QBCore:Client:OnPlayerUnload", function() LogOut() end)

When a character has been loaded, trigger FetchPhone() to load the phone.

-- This is an example from the lb-phone qb.lua file RegisterNetEvent("QBCore:Client:OnPlayerLoaded", function() FetchPhone() end)

Money change

When the player’s money changes, you can trigger the wallet:setBalance NUI event to update the wallet balance.

SendReactMessage("wallet:setBalance", math.floor(bankBalance))

Inventory item removal

When an item is removed from the player’s inventory, you can add a check if the player has a phone item. If not, close the phone.

-- This is an example from the lb-phone esx.lua file RegisterNetEvent("esx:removeInventoryItem", function(item, count) -- Check if the config requires a phone item if not Config.Item.Require or Config.Item.Unique or item ~= Config.Item.Name or count > 0 then return end -- This wait allows various variables to update, fixing race conditions Wait(500) if not HasPhoneItem() then -- OnDeath closes the phone, ends calls etc. OnDeath() end end)

Framework functions

You need to implement the following functions for the phone to work with your framework.

HasPhoneItem

Check if the player has the phone item in their inventory.

---@param number?: string # The phone number to check (if using unique phones) ---@return boolean function HasPhoneItem(number) if not Config.Item.Require then return true end if Config.Item.Unique then -- HasPhoneNumber is a function defined in the unique phones file return HasPhoneNumber(number) end -- Implement your own check here return true end

HasJob

Check if the player has one of various jobs

---@param jobs string[] ---@return boolean function HasJob(jobs) -- Edit this to get the player's job local job = ESX.PlayerData.job.name for i = 1, #jobs do if jobs[i] == job then return true end end return false end

Garage functions

ApplyVehicleMods

Apply vehicle mods to a vehicle

---@param vehicle number ---@param vehicleData table function ApplyVehicleMods(vehicle, vehicleData) end

CreateFrameworkVehicle

Create a vehicle and apply mods

---@param vehicleData table ---@param coords vector3 ---@return number? vehicle function CreateFrameworkVehicle(vehicleData, coords) local model = LoadModel(vehicleData.model) local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, 0.0, true, false) ApplyVehicleMods(vehicle, vehicleData) return vehicle end

Companies/services functions

GetCompanyData

This function should callback or return the company data for the player’s job.

---@param cb fun(companyData: table) function GetCompanyData(cb) local companyData = {} return companyData end

The company data should return the following:

  • job: string
  • jobLabel: string
  • isBoss: boolean
  • duty?: boolean - optional. Requires the ToggleDuty function to be implemented. For the toggle duty button to show, duty has to be true or false, not nil.

If the player is a boss, also return the following:

  • balance: number - The company’s bank balance
  • employees: Employee[] - A list of employees
    • name: string
    • id: string - the player’s identifier
    • gradeLabel: string
    • grade: string
    • canInteract: boolean - Whether the player can interact with this employee (fire, promote etc.)
  • grades: Grade[]
    • label: string
    • grade: any

DepositMoney

Deposit money into the company’s bank account. Return or callback the updated bank balance.

---@param amount number ---@param cb fun(amount: number) function DepositMoney(amount, cb) -- Implement your deposit function here return newBalance end

WithdrawMoney

Withdraw money from the company’s bank account. Return or callback the updated bank balance.

---@param amount number ---@param cb fun(amount: number) function WithdrawMoney(amount, cb) -- Implement your withdraw function here return newBalance end

HireEmployee

Hire an employee. Return or callback the player data of the new employee (name & id).

---@param source number ---@param cb fun(employee: Employee) function HireEmployee(source, cb) -- Implement your hire function here return { name = "John Doe", id = "license:1234567890" } end

FireEmployee

Fire an employee. Return or callback boolean

---@param id string ---@param cb fun(success: boolean) function FireEmployee(id, cb) -- Implement your fire function here return true end

SetGrade

Promote/demote an employee. Return or callback boolean

---@param id string ---@param grade string ---@param cb fun(success: boolean) function SetGrade(id, grade, cb) -- Implement your set grade function here return true end

ToggleDuty

Optional. Toggle the player’s duty status. You do not need to return anything.

function ToggleDuty() -- Implement your duty toggle function here TriggerServerEvent("QBCore:ToggleDuty") end