Cadburry ScriptsCadburry Scripts

Multicharacter (Optional)

Quality of life scripts for your FiveM server. Performance optimized resources that install in minutes, with free updates and support that actually answers.

Cad Characters

Works out of the box ( just start cad-queue before cad-characters )

QB Multicharacter

Replace below function in qb-multicharacter/server/main.lua

lua
QBCore.Functions.CreateCallback('qb-multicharacter:server:setupCharacters', function(source, cb)
    local license = QBCore.Functions.GetIdentifier(source, 'license')
    local discord = GetPlayerIdentifierByType(source, 'discord')
    if not discord then return cb({}) end
    local data = exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'
    local plyChars = {}
    local result = MySQL.query.await('SELECT * FROM players WHERE license = ?', { license })
    if result then
        for i = 1, (#result), 1 do
            result[i].charinfo = json.decode(result[i].charinfo)
            result[i].money = json.decode(result[i].money)
            result[i].job = json.decode(result[i].job)

            local job = result[i].job
            if (jobName == 'all') or (job?.name ~= jobName) then
                plyChars[#plyChars + 1] = result[i]
            end
        end
    end
    cb(plyChars)
end)

Snappy Characters - ESX/QB/QBOX

ESX: Replace below function in snappy-characters/bridge/framework/server/esx.lua

lua
function GetAllCharacters(src)
    local identifier = ESX.GetIdentifier(src)
    local discord = GetPlayerIdentifierByType(src, 'discord') -- add the identifier which you are using in `Config.Identifier` in cad-queue
    if not discord then return {} end
    local data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'
    local characters = {}
    local result = MySQL.query.await("SELECT identifier, job, firstname, lastname, dateofbirth, sex, skin, disabled FROM users WHERE identifier LIKE ?", { ("%s%%:%s"):format('char', identifier) })
    if result and result[1] then
        for _, v in pairs(result) do
            local job = v.job
            local gender = v.sex == 'm' and 'Male' or 'Female'
            characters[#characters+1] = {
                charInfo = {
                    firstName = v.firstname,
                    lastName = v.lastname,
                    dateOfBirth = v.dateofbirth,
                    nationality = v.nationality,
                    gender = gender,
                    citizenId = v.identifier
                },
                skinData = GetSkinData(v.identifier),
                isLocked = (jobName ~= 'all' and job ~= jobName) or (v.disabled ~= 0),
                businessName = job
            }
        end
    end
    return characters
end

QB: Replace below function in snappy-characters/bridge/framework/server/qb.lua

lua
function GetAllCharacters(src)
    local license = GetPlayerIdentifierByType(src, 'license')
    local discord = GetPlayerIdentifierByType(src, 'discord') -- add the identifier which you are using in `Config.Identifier` in cad-queue
    if not discord then return {} end
    local data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'
    local characters = {}
    local result = MySQL.query.await('SELECT citizenid, charinfo, job FROM players WHERE license = ?', { license })
    if result and result[1] then
        for _, v in pairs(result) do
            local jobInfo = (v.job and json.decode(v.job)) or { name = 'none' }
            local charInfo = json.decode(v.charinfo)
            local gender = (charInfo.gender ~= 1 and 'Female') or 'Male'
            characters[#characters+1] = {
                charInfo = {
                    firstName = charInfo.firstname,
                    lastName = charInfo.lastname,
                    dateOfBirth = charInfo.birthdate,
                    nationality = charInfo.nationality,
                    gender = gender,
                    citizenId = v.citizenid
                },
                skinData = GetSkinData(v.citizenid),
                isLocked = (jobName ~= 'all' and jobInfo.name ~= jobName),
                businessName = jobInfo.label
            }
        end
    end
    return characters
end

QBOX: Replace below function in snappy-characters/bridge/framework/server/qbox.lua

lua
function GetAllCharacters(src)
    local license, license2 = GetPlayerIdentifierByType(src, 'license2'), GetPlayerIdentifierByType(src, 'license')
    local discord = GetPlayerIdentifierByType(src, 'discord') -- add the identifier which you are using in `Config.Identifier` in cad-queue
    if not discord then return {} end
    local data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'
    local characters = {}
    local result = MySQL.query.await('SELECT citizenid, charinfo, job FROM players WHERE license IN (?, ?)', { license, license2 })
    if result and result[1] then
        for _, v in pairs(result) do
            local jobInfo = (v.job and json.decode(v.job)) or { name = 'none' }
            local charInfo = json.decode(v.charinfo)
            local gender = (charInfo.gender ~= 1 and 'Female') or 'Male'
            characters[#characters+1] = {
                charInfo = {
                    firstName = charInfo.firstname,
                    lastName = charInfo.lastname,
                    dateOfBirth = charInfo.birthdate,
                    nationality = charInfo.nationality,
                    gender = gender,
                    citizenId = v.citizenid
                },
                skinData = GetSkinData(v.citizenid),
                isLocked = (jobName ~= 'all' and jobInfo.name ~= jobName),
                businessName = jobInfo.label
            }
        end
    end
    return characters
end

Forge Multicharacter (ESX/QB/QBOX)

ESX: Replace below function in forge-multicharacter/server/frameworks/ESX.lua

lua
function ST.ESX:LoadCharacters(source, cb)
    local discord = GetPlayerIdentifierByType(source, 'discord')
    local data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'

    local roles = {}
    if Config.bot.use then
        roles = GetDiscordRoles(source)
        if roles == nil then
            DropPlayer(source, "Missing discord Identifier")
        end
    end

    local characters = {}
    local queryIdentifier = FormatIdentifier(IdentifierFormatTable(source, "%%"))
    local query = "SELECT * FROM `users` WHERE `identifier` LIKE '" .. tostring(queryIdentifier) .. "'"
    MySQL.Async.fetchAll(query, {}, function(results)
        local addSlots = 0
        if results then
            if #results > 0 then
                for _, char in ipairs(results) do
                    debug("char" .. tostring(_) .. ": " .. json.encode(char))
                    local location = json.decode(char.position)
                    local accounts = json.decode(char.accounts)
                    local sex = 0
                    -- cache update!
                    if char.sex == "m" then
                        sex = 1
                    end
                    local jobLabel = self:GetJobLabel(char.job)
                    if (jobName == 'all') or (char.job == jobName) then
                        table.insert(characters, {
                            identifier = char.identifier,
                            name = char.firstname .. " " .. char.lastname,
                            lastSpawnPoint = location,
                            cash = accounts.money,
                            bank = accounts.bank,
                            gender = sex,
                            job = jobLabel,
                            skin = json.decode(char.skin),
                            grade = char.job_grade,
                            playTime = FormatPlayTime(char.playtime),
                            nationality = char.nationality
                        })
                    end
                end
            end
        end
        addSlots = (MySQL.query.await('SELECT `slots` FROM `additionalSlots` WHERE `identifier`=?', {
            GetPlayerIdentifierByType(source, 'license')
        })[1] or {}).slots or 0
        cb(source, characters, roles, addSlots)
    end)
end

QB/QBOX: Replace below function in forge-multicharacter/server/frameworks/QB.lua

lua
function ST.QB:LoadCharacters(source, cb)
    local license = self:GetIdentifier(source)
    local discord = GetPlayerIdentifierByType(source, 'discord')
    local data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord)
    local jobName = (data and data.name) or 'all'
    
    -- QBOX/QBCore compatibility check
    if QBCore and QBCore.Players then
        QBCore.Players[license] = true
    else
        debug("Warning: QBCore.Players is nil - possible QBOX compatibility issue")
    end
    
    local roles = {}
    if Config.bot.use then
        roles = GetDiscordRoles(source)
        if roles == nil then
            DropPlayer(source, "Missing discord Identifier")
        end
    end

    local characters = {}
    local query =
    "SELECT * FROM `players`, `playerskins` WHERE `license` LIKE @license AND `players`.`citizenid`=`playerskins`.`citizenid`"
    MySQL.Async.fetchAll(query, {
        ['@license'] = '%' .. license .. '%'
    }, function(results)
        local addSlots = 0
        if results then
            if #results > 0 then
                for _, char in ipairs(results) do
                    local location = json.decode(char.position)
                    local accounts = json.decode(char.money)
                    local job = json.decode(char.job)
                    local charinfo = json.decode(char.charinfo)
                    local sex = charinfo.gender == 0 and 1 or 0

                    local shareChar = {
                        identifier = char.citizenid,
                        name = charinfo.firstname .. " " .. charinfo.lastname,
                        lastSpawnPoint = location,
                        cash = accounts.cash,
                        bank = accounts.bank,
                        gender = sex,
                        job = job.label,
                        skin = json.decode(char.skin),
                        grade = job.grade.level,
                        playTime = FormatPlayTime(char.playtime),
                        nationality = charinfo.nationality
                    }
                    shareChar.skin.model = char.model

                    if (jobName == 'all') or (job?.name == jobName) then
                        table.insert(characters, shareChar)
                    end
                end
                addSlots = (MySQL.query.await('SELECT `slots` FROM `additionalSlots` WHERE `identifier`=?', {
                    license
                })[1] or {}).slots or 0
            end
        end
        cb(source, characters, roles, addSlots)
    end)
end

ZSX Multicharacter

Replace below function in ZSX_Multicharacter/server/functions/characters.lua

lua
Characters.Get = function(src)
    local identifier = Characters.GetIdentifier(src)
    local PREFIX = Config.Prefix or 'char'
    local query
    if FrameworkSelected == 'ESX' then
        query = "SELECT * FROM `users` WHERE identifier LIKE '%"..identifier.."'"
    elseif FrameworkSelected == 'QBCore' then
        query = "SELECT * FROM `players` WHERE `license` = '"..identifier.."'"
    end
    local discord = GetPlayerIdentifierByType(src, 'discord')
    local queue_data = (GetResourceState('cad-queue') == 'started') and exports['cad-queue']:GetPrio(discord) -- added
    local queue_job_name = (queue_data and queue_data.name) or 'all' -- added
    local response = MySQL.query.await(query)
    local characters = {}
    local startTime = GetGameTimer()
    debugPrint("[^2CHARACTERS.GET^7] Gathering NUI Data [/]")
    for k,v in ipairs(response) do
        if FrameworkSelected == 'ESX' then
            local checkMulticharacterMode = string.sub(v.identifier, 1, string.len(PREFIX)) == PREFIX
            assert(checkMulticharacterMode, '^5Your es_extended does not use Config.Multichar. Player identifier: ^3'..v.identifier..'\n^2Please refer to the docs: https://zsx-development.gitbook.io/docs/multicharacter/common-issues/esx\n\n')
        end
        local id = FrameworkSelected == 'ESX' and tonumber(string.sub(v.identifier, #PREFIX+1, string.find(v.identifier, ':')-1)) or FrameworkSelected == 'QBCore' and tonumber(v.cid)
        if FrameworkSelected == 'ESX' then
            local job = v.job
            local grade = v.job_grade
            if GetResourceState('origen_masterjob') == 'started' then
                if not Characters.Jobs[job] then
                    local business = exports["origen_masterjob"]:GetBusiness(job)
                    if business then
                        local gradeObject = business.Functions.GetGrade(grade)
                        if gradeObject then
                            if not Characters.JobGrades[job] then
                                Characters.JobGrades[job] = {}
                            end
                            Characters.Jobs[job] = business.Data.label
                            Characters.JobGrades[job][tonumber(grade)] = gradeObject.label or ''
                            debugPrint('[ORIGEN_MASTERJOB] Applied changes to the Jobs and JobGrades objects. Job: ['..job..']')
                        else
                            debugPrint('[ORIGEN_MASTERJOB] No business grade has been found for: ['..job..']')
                        end
                    else
                        debugPrint('[ORIGEN_MASTERJOB] No business has been found for: ['..job..']')
                    end
                end
            end
           
            assert(v.position ~= nil and v.position ~= '', '^5Failed to get player position. Player identifier: ^3'..v.identifier..'\n^2Please refer to the docs: https://zsx-development.gitbook.io/docs/multicharacter/common-issues/esx\n\n')
            v.job = {
                name = job,
                label = Characters.Jobs[job] or 'Unemployed',
                grade_label = Characters.JobGrades[job] and Characters.JobGrades[job][tonumber(grade)] or ''
            }
            if (queue_job_name == 'all' or (v.job and v.job.name == queue_job_name)) then -- added
                local coords = json.decode(v.position)
                v.position = coords
                v.id = id
                v.skin = Characters.ConvertSkin(v.identifier)
                table.insert(characters, v)
            end -- added
        elseif FrameworkSelected == 'QBCore' then
            local skinResponse = MySQL.query.await("SELECT * FROM `playerskins` WHERE `citizenid` = '"..v.citizenid.."' AND active = 1")
            local responseCharData = json.decode(v.charinfo)
            local responseJobData = json.decode(v.job)
            if (queue_job_name == 'all' or (responseJobData and responseJobData.name == queue_job_name)) then -- added
                local characterData = {
                    sex = tonumber(response[1].gender) == 0 and 'm' or 'f',
                    skin = Characters.ConvertSkin(v.citizenid),
                    model = skinResponse[1] and tonumber(skinResponse[1].model) or false,
                    position = json.decode(v.position),
                    firstname = responseCharData.firstname,
                    lastname = responseCharData.lastname,
                    job = {
                        name = responseJobData.name,
                        label = responseJobData.label,
                        grade_label = responseJobData.grade and responseJobData.grade.name or ''
                    },
                    id = id
                }
                table.insert(characters, characterData)
            end -- added
        end
    end
    if Config.DebugTimers then
        print('[CHARACTERS.GET] Took: ^3'..(GetGameTimer() - startTime)..'ms^7')
    end
    debugPrint("[^2CHARACTERS.GET^7] Gathered NUI Data")
    return characters
end
Last updated Cadburry Scripts