309 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local QBCore = exports['qb-core']:GetCoreObject()
 | 
						|
 | 
						|
local function GetJobs(citizenid)
 | 
						|
    local p = promise.new()
 | 
						|
    MySQL.Async.fetchAll("SELECT jobdata FROM multijobs WHERE citizenid = @citizenid",{
 | 
						|
        ["@citizenid"] = citizenid
 | 
						|
    }, function(jobs)
 | 
						|
        if jobs[1] and jobs ~= "[]" then
 | 
						|
            jobs = json.decode(jobs[1].jobdata)
 | 
						|
        else
 | 
						|
            local Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid)
 | 
						|
            local temp = {}
 | 
						|
            if not Config.IgnoredJobs[Player.PlayerData.job.name] then
 | 
						|
                temp[Player.PlayerData.job.name] = Player.PlayerData.job.grade.level
 | 
						|
                MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', {
 | 
						|
                    citizenid = citizenid,
 | 
						|
                    jobdata = json.encode(temp),
 | 
						|
                })
 | 
						|
            end
 | 
						|
            jobs = temp
 | 
						|
        end
 | 
						|
        p:resolve(jobs)
 | 
						|
    end)
 | 
						|
    return Citizen.Await(p)
 | 
						|
end
 | 
						|
exports("GetJobs", GetJobs)
 | 
						|
    
 | 
						|
local function AddJob(citizenid, job, grade)
 | 
						|
    local jobs = GetJobs(citizenid)
 | 
						|
    for ignored in pairs(Config.IgnoredJobs) do
 | 
						|
        if jobs[ignored] then
 | 
						|
            jobs[ignored] = nil
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    jobs[job] = grade
 | 
						|
    MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', {
 | 
						|
        citizenid = citizenid,
 | 
						|
        jobdata = json.encode(jobs),
 | 
						|
    })
 | 
						|
end
 | 
						|
exports("AddJob", AddJob)
 | 
						|
 | 
						|
local function UpdatePlayerJob(Player, job, grade)
 | 
						|
    if Player.PlayerData.source ~= nil then
 | 
						|
        Player.Functions.SetJob(job,grade)
 | 
						|
    else -- player is offline
 | 
						|
        local sharedJobData = QBCore.Shared.Jobs[job]
 | 
						|
        if sharedJobData == nil then return end
 | 
						|
 | 
						|
        local sharedGradeData = sharedJobData.grades[grade]
 | 
						|
        if sharedGradeData == nil then return end
 | 
						|
 | 
						|
        local isBoss = false
 | 
						|
        if sharedGradeData.isboss then isBoss = true end
 | 
						|
 | 
						|
        MySQL.update.await("update players set job = @jobData where citizenid = @citizenid", {
 | 
						|
            jobData = json.encode({
 | 
						|
                label = sharedJobData.label,
 | 
						|
                name = job,
 | 
						|
                isboss = isBoss,
 | 
						|
                onduty = sharedJobData.defaultDuty,
 | 
						|
                payment = sharedGradeData.payment,
 | 
						|
                grade = {
 | 
						|
                    name = sharedGradeData.name,
 | 
						|
                    level = grade,
 | 
						|
                },
 | 
						|
            }),
 | 
						|
            citizenid = Player.PlayerData.citizenid
 | 
						|
        })
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
local function UpdateJobRank(citizenid, job, grade)
 | 
						|
    local Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid)
 | 
						|
    if Player == nil then
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local jobs = GetJobs(citizenid)
 | 
						|
    if jobs[job] == nil then
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    jobs[job] = grade
 | 
						|
    
 | 
						|
    MySQL.update.await("update multijobs set jobdata = :jobdata where citizenid = :citizenid", {
 | 
						|
        citizenid = citizenid,
 | 
						|
        jobdata = json.encode(jobs),
 | 
						|
    })
 | 
						|
    
 | 
						|
    -- if the current job matches, then update
 | 
						|
    if Player.PlayerData.job.name == job then
 | 
						|
        UpdatePlayerJob(Player, job, grade)
 | 
						|
    end
 | 
						|
end
 | 
						|
exports("UpdateJobRank", UpdateJobRank)
 | 
						|
 | 
						|
local function RemoveJob(citizenid, job)
 | 
						|
    local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)
 | 
						|
 | 
						|
    if Player == nil then
 | 
						|
        Player = QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid)
 | 
						|
    end
 | 
						|
 | 
						|
    if Player == nil then return end
 | 
						|
 | 
						|
    local jobs = GetJobs(citizenid)
 | 
						|
    jobs[job] = nil
 | 
						|
 | 
						|
    -- Since we removed a job, put player in a new job
 | 
						|
    local foundNewJob = false
 | 
						|
    if Player.PlayerData.job.name == job then
 | 
						|
        for k,v in pairs(jobs) do
 | 
						|
            UpdatePlayerJob(Player, k,v)
 | 
						|
            foundNewJob = true
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    if not foundNewJob then
 | 
						|
        UpdatePlayerJob(Player, "unemployed", 0)
 | 
						|
    end
 | 
						|
 | 
						|
    MySQL.insert('INSERT INTO multijobs (citizenid, jobdata) VALUES (:citizenid, :jobdata) ON DUPLICATE KEY UPDATE jobdata = :jobdata', {
 | 
						|
        citizenid = citizenid,
 | 
						|
        jobdata = json.encode(jobs),
 | 
						|
    })
 | 
						|
end
 | 
						|
exports("RemoveJob", RemoveJob)
 | 
						|
 | 
						|
QBCore.Commands.Add('removejob', 'Remove Multi Job (Admin Only)', { { name = 'id', help = 'ID of player' }, { name = 'job', help = 'Job Name' } }, false, function(source, args)
 | 
						|
    local source = source
 | 
						|
    if source ~= 0 then
 | 
						|
        if args[1] then
 | 
						|
            local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
 | 
						|
            if Player then
 | 
						|
                if args[2] then
 | 
						|
                    RemoveJob(Player.PlayerData.citizenid, args[2])
 | 
						|
                else
 | 
						|
                    TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
                end
 | 
						|
            else
 | 
						|
                TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
            end
 | 
						|
        else
 | 
						|
            TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
    end
 | 
						|
end, 'admin')
 | 
						|
 | 
						|
QBCore.Commands.Add('addjob', 'Add Multi Job (Admin Only)', { { name = 'id', help = 'ID of player' }, { name = 'job', help = 'Job Name' }, { name = 'grade', help = 'Job Grade' } }, false, function(source, args)
 | 
						|
    local source = source
 | 
						|
    if source ~= 0 then
 | 
						|
        if args[1] then
 | 
						|
            local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
 | 
						|
            if Player then
 | 
						|
                if args[2]and args[3] then
 | 
						|
                    AddJob(Player.PlayerData.citizenid, args[2], args[3])
 | 
						|
                else
 | 
						|
                    TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
                end
 | 
						|
            else
 | 
						|
                TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
            end
 | 
						|
        else
 | 
						|
            TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent("QBCore:Notify", source, "Wrong usage!")
 | 
						|
    end
 | 
						|
end, 'admin')
 | 
						|
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback("ps-multijob:getJobs", function(source, cb)
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    local jobs = GetJobs(Player.PlayerData.citizenid)
 | 
						|
    local multijobs = {}
 | 
						|
    local whitelistedjobs = {}
 | 
						|
    local civjobs = {}
 | 
						|
    local active = {}
 | 
						|
    local pendingJobs = {} -- Track jobs that might be loaded later
 | 
						|
 | 
						|
    -- Initialize active jobs count
 | 
						|
    local Players = QBCore.Functions.GetPlayers()
 | 
						|
    for i = 1, #Players, 1 do
 | 
						|
        local xPlayer = QBCore.Functions.GetPlayer(Players[i])
 | 
						|
        if xPlayer then
 | 
						|
            active[xPlayer.PlayerData.job.name] = active[xPlayer.PlayerData.job.name] or 0
 | 
						|
            if xPlayer.PlayerData.job.onduty then
 | 
						|
                active[xPlayer.PlayerData.job.name] = active[xPlayer.PlayerData.job.name] + 1
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    for job, grade in pairs(jobs) do
 | 
						|
        if QBCore.Shared.Jobs[job] == nil then
 | 
						|
            -- Store this job for later processing
 | 
						|
            pendingJobs[job] = grade
 | 
						|
        else
 | 
						|
            local online = active[job] or 0
 | 
						|
            local getjobs = {
 | 
						|
                name = job,
 | 
						|
                grade = grade,
 | 
						|
                description = Config.Descriptions[job] or "No description available",
 | 
						|
                icon = Config.FontAwesomeIcons[job] or "fa-solid fa-briefcase",
 | 
						|
                label = QBCore.Shared.Jobs[job].label,
 | 
						|
                active = online,
 | 
						|
            }
 | 
						|
            
 | 
						|
            -- Safer access to grade properties
 | 
						|
            if QBCore.Shared.Jobs[job].grades and QBCore.Shared.Jobs[job].grades[tostring(grade)] then
 | 
						|
                getjobs.gradeLabel = QBCore.Shared.Jobs[job].grades[tostring(grade)].name or "Unknown"
 | 
						|
                getjobs.salary = QBCore.Shared.Jobs[job].grades[tostring(grade)].payment or 0
 | 
						|
            else
 | 
						|
                getjobs.gradeLabel = "Unknown"
 | 
						|
                getjobs.salary = 0
 | 
						|
            end
 | 
						|
            
 | 
						|
            if Config.WhitelistJobs[job] then
 | 
						|
                whitelistedjobs[#whitelistedjobs+1] = getjobs
 | 
						|
            else
 | 
						|
                civjobs[#civjobs+1] = getjobs
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    multijobs = {
 | 
						|
        whitelist = whitelistedjobs,
 | 
						|
        civilian = civjobs,
 | 
						|
    }
 | 
						|
    cb(multijobs)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent("ps-multijob:changeJob",function(cjob, cgrade)
 | 
						|
    local source = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
 | 
						|
    if cjob == "unemployed" and cgrade == 0 then
 | 
						|
        Player.Functions.SetJob(cjob, cgrade)
 | 
						|
        return
 | 
						|
    end
 | 
						|
 | 
						|
    local jobs = GetJobs(Player.PlayerData.citizenid)
 | 
						|
    for job, grade in pairs(jobs) do
 | 
						|
        if cjob == job and cgrade == grade then
 | 
						|
            Player.Functions.SetJob(job, grade)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent("ps-multijob:removeJob",function(job, grade)
 | 
						|
    local source = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    RemoveJob(Player.PlayerData.citizenid, job)
 | 
						|
end)
 | 
						|
 | 
						|
-- QBCORE EVENTS
 | 
						|
 | 
						|
RegisterNetEvent('ps-multijob:server:removeJob', function(targetCitizenId)
 | 
						|
    MySQL.Async.execute('DELETE FROM multijobs WHERE citizenid = ?', { targetCitizenId }, function(affectedRows)
 | 
						|
        if affectedRows > 0 then
 | 
						|
            print('Removed job: ' .. targetCitizenId)
 | 
						|
        else
 | 
						|
            print('Cannot remove job: ' .. targetCitizenId)
 | 
						|
        end
 | 
						|
    end)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('QBCore:Server:OnJobUpdate', function(source, newJob)
 | 
						|
    local source = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    local jobs = GetJobs(Player.PlayerData.citizenid)
 | 
						|
    local amount = 0
 | 
						|
    local setjob = newJob
 | 
						|
    for k,v in pairs(jobs) do
 | 
						|
        amount = amount + 1
 | 
						|
    end
 | 
						|
 | 
						|
    local maxJobs = Config.MaxJobs
 | 
						|
    if QBCore.Functions.HasPermission(source, "admin") then
 | 
						|
        maxJobs = math.huge
 | 
						|
    end
 | 
						|
 | 
						|
    if amount < maxJobs and not Config.IgnoredJobs[setjob.name] then
 | 
						|
        local foundOldJob = jobs[setjob.name]
 | 
						|
        if not foundOldJob or foundOldJob ~= setjob.grade.level then
 | 
						|
            AddJob(Player.PlayerData.citizenid, setjob.name, setjob.grade.level)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Add the event listener for jobs_creator
 | 
						|
RegisterNetEvent("jobs_creator:injectJobs", function(jobs)
 | 
						|
    -- This will run when jobs are injected by jobs_creator
 | 
						|
    print("ps-multijob: Jobs have been updated by jobs_creator")
 | 
						|
    
 | 
						|
    -- Optional: You could notify online players that jobs have been updated
 | 
						|
    -- This would allow them to refresh their job menu to see any new jobs
 | 
						|
    local Players = QBCore.Functions.GetPlayers()
 | 
						|
    for i = 1, #Players do
 | 
						|
        local Player = QBCore.Functions.GetPlayer(Players[i])
 | 
						|
        if Player then
 | 
						|
            TriggerClientEvent('QBCore:Notify', Players[i], "Job system has been updated", "success")
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 |