363 lines
14 KiB
Lua
363 lines
14 KiB
Lua
lib.versionCheck('Qbox-project/qbx_management')
|
|
if not lib.checkDependency('qbx_core', '1.18.0', true) then error() return end
|
|
if not lib.checkDependency('ox_lib', '3.13.0', true) then error() return end
|
|
|
|
local config = require 'config.server'
|
|
local logger = require '@qbx_core.modules.logger'
|
|
local JOBS = exports.qbx_core:GetJobs()
|
|
local GANGS = exports.qbx_core:GetGangs()
|
|
local playersClockedIn = {}
|
|
local menus = {}
|
|
|
|
for groupName, menuInfo in pairs(config.menus) do
|
|
---@diagnostic disable-next-line: inject-field
|
|
menuInfo.groupName = groupName
|
|
menus[#menus + 1] = menuInfo
|
|
end
|
|
|
|
local function getMenuEntries(groupName, groupType)
|
|
local menuEntries = {}
|
|
|
|
local groupEntries = exports.qbx_core:GetGroupMembers(groupName, groupType)
|
|
for i = 1, #groupEntries do
|
|
local citizenid = groupEntries[i].citizenid
|
|
local grade = groupEntries[i].grade
|
|
local player = exports.qbx_core:GetPlayerByCitizenId(citizenid) or exports.qbx_core:GetOfflinePlayer(citizenid)
|
|
local namePrefix = player.Offline and '❌ ' or '🟢 '
|
|
local playerActivityData = groupType == 'job' and GetPlayerActivityData(citizenid, groupName) or nil
|
|
local playerClockData = playersClockedIn[player.PlayerData.source]
|
|
local playerLastCheckIn = playerClockData and os.date(config.formatDateTime, playerClockData.time) or playerActivityData?.last_checkin
|
|
menuEntries[#menuEntries + 1] = {
|
|
cid = citizenid,
|
|
grade = grade,
|
|
name = namePrefix..player.PlayerData.charinfo.firstname..' '..player.PlayerData.charinfo.lastname,
|
|
onduty = player.PlayerData.job.onduty and not player.Offline,
|
|
hours = playerActivityData?.hours,
|
|
last_checkin = playerLastCheckIn
|
|
}
|
|
end
|
|
|
|
return menuEntries
|
|
end
|
|
|
|
-- Get a list of employees for a given group.
|
|
---@param groupName string Name of job/gang to get employees of
|
|
---@param groupType GroupType
|
|
---@return table?
|
|
lib.callback.register('qbx_management:server:getEmployees', function(source, groupName, groupType)
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
if not player.PlayerData[groupType].isboss then return end
|
|
|
|
local menuEntries = getMenuEntries(groupName, groupType)
|
|
table.sort(menuEntries, function(a, b)
|
|
return a.grade > b.grade
|
|
end)
|
|
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:getEmployees',
|
|
message = locale('logs.retrieved_employees', groupName, groupType),
|
|
webhook = config.discordWebhook
|
|
})
|
|
|
|
return menuEntries
|
|
end)
|
|
|
|
-- Callback for updating the grade information of online players
|
|
---@param source number
|
|
---@param citizenId string CitizenId of player who is being promoted/demoted
|
|
---@param oldGrade integer Old grade number of target employee
|
|
---@param newGrade integer New grade number of target employee
|
|
---@param groupType GroupType
|
|
lib.callback.register('qbx_management:server:updateGrade', function(source, citizenId, oldGrade, newGrade, groupType)
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
local employee = exports.qbx_core:GetPlayerByCitizenId(citizenId)
|
|
local jobName = player.PlayerData[groupType].name
|
|
local gradeLevel = player.PlayerData[groupType].grade.level
|
|
|
|
if not player.PlayerData[groupType].isboss then return end
|
|
|
|
if player.PlayerData.citizenid == citizenId then
|
|
exports.qbx_core:Notify(source, locale('error.cant_promote_self'), 'error')
|
|
return
|
|
end
|
|
|
|
if oldGrade >= gradeLevel or newGrade >= gradeLevel then
|
|
exports.qbx_core:Notify(source, locale('error.cant_promote'), 'error')
|
|
return
|
|
end
|
|
|
|
if groupType == 'job' then
|
|
local success, errorResult = exports.qbx_core:AddPlayerToJob(citizenId, jobName, newGrade)
|
|
assert(success, errorResult?.message)
|
|
else
|
|
local success, errorResult = exports.qbx_core:AddPlayerToGang(citizenId, jobName, newGrade)
|
|
assert(success, errorResult?.message)
|
|
end
|
|
|
|
if employee then
|
|
local gradeName = groupType == 'gang' and GANGS[jobName].grades[newGrade].name or JOBS[jobName].grades[newGrade].name
|
|
exports.qbx_core:Notify(employee.PlayerData.source, locale('success.promoted_to')..gradeName..'.', 'success')
|
|
end
|
|
exports.qbx_core:Notify(source, locale('success.promoted'), 'success')
|
|
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:updateGrade',
|
|
message = locale('logs.updated_grade', citizenId, oldGrade, newGrade, jobName, groupType),
|
|
webhook = config.discordWebhook
|
|
})
|
|
end)
|
|
|
|
-- Callback to hire online player as employee of a given group
|
|
---@param employee integer Server ID of target employee to be hired
|
|
---@param groupType GroupType
|
|
lib.callback.register('qbx_management:server:hireEmployee', function(source, employee, groupType)
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
local target = exports.qbx_core:GetPlayer(employee)
|
|
|
|
if not player.PlayerData[groupType].isboss then return end
|
|
|
|
if not target then
|
|
exports.qbx_core:Notify(source, locale('error.not_around'), 'error')
|
|
return
|
|
end
|
|
|
|
local groupName = player.PlayerData[groupType].name
|
|
local logArea = groupType == 'gang' and 'Gang' or 'Boss'
|
|
|
|
if groupType == 'job' then
|
|
local success, errorResult = exports.qbx_core:AddPlayerToJob(target.PlayerData.citizenid, groupName, 0)
|
|
assert(success, errorResult?.message)
|
|
success, errorResult = exports.qbx_core:SetPlayerPrimaryJob(target.PlayerData.citizenid, groupName)
|
|
assert(success, errorResult?.message)
|
|
else
|
|
local success, errorResult = exports.qbx_core:AddPlayerToGang(target.PlayerData.citizenid, groupName, 0)
|
|
assert(success, errorResult?.message)
|
|
success, errorResult = exports.qbx_core:SetPlayerPrimaryGang(target.PlayerData.citizenid, groupName)
|
|
assert(success, errorResult?.message)
|
|
end
|
|
|
|
local playerFullName = player.PlayerData.charinfo.firstname..' '..player.PlayerData.charinfo.lastname
|
|
local targetFullName = target.PlayerData.charinfo.firstname..' '..target.PlayerData.charinfo.lastname
|
|
local organizationLabel = player.PlayerData[groupType].label
|
|
|
|
exports.qbx_core:Notify(source, locale('success.hired_into', targetFullName, organizationLabel), 'success')
|
|
exports.qbx_core:Notify(target.PlayerData.source, locale('success.hired_to')..organizationLabel, 'success')
|
|
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:hireEmployee',
|
|
message = locale('logs.hired_employee', logArea, playerFullName, targetFullName, organizationLabel, 0),
|
|
webhook = config.discordWebhook
|
|
})
|
|
end)
|
|
|
|
-- Returns playerdata for a given table of player server ids.
|
|
---@param closePlayers table Table of player data for possible hiring
|
|
---@return table
|
|
lib.callback.register('qbx_management:server:getPlayers', function(_, closePlayers)
|
|
local players = {}
|
|
for _, v in pairs(closePlayers) do
|
|
local player = exports.qbx_core:GetPlayer(v.id)
|
|
players[#players + 1] = {
|
|
id = v.id,
|
|
name = player.PlayerData.charinfo.firstname..' '..player.PlayerData.charinfo.lastname,
|
|
citizenid = player.PlayerData.citizenid,
|
|
job = player.PlayerData.job,
|
|
gang = player.PlayerData.gang,
|
|
source = player.PlayerData.source
|
|
}
|
|
end
|
|
|
|
table.sort(players, function(a, b)
|
|
return a.name < b.name
|
|
end)
|
|
|
|
logger.log({
|
|
source = 'qbx_management',
|
|
event = 'qbx_management:server:getPlayers',
|
|
message = locale('logs.retrieved_players'),
|
|
webhook = config.discordWebhook
|
|
})
|
|
|
|
return players
|
|
end)
|
|
|
|
|
|
---@param employeeCitizenId string
|
|
---@diagnostic disable-next-line: undefined-doc-name
|
|
---@param boss Player | table
|
|
---@param groupName string
|
|
---@param groupType GroupType
|
|
---@return boolean success
|
|
local function fireEmployee(employeeCitizenId, boss, groupName, groupType)
|
|
local employee = exports.qbx_core:GetPlayerByCitizenId(employeeCitizenId) or exports.qbx_core:GetOfflinePlayer(employeeCitizenId)
|
|
|
|
if employee.PlayerData.citizenid == boss.PlayerData.citizenid then
|
|
local message = groupType == 'gang' and locale('error.kick_yourself') or locale('error.fire_yourself')
|
|
exports.qbx_core:Notify(boss.PlayerData.source, message, 'error')
|
|
return false
|
|
end
|
|
|
|
if not employee then
|
|
exports.qbx_core:Notify(boss.PlayerData.source, locale('error.person_doesnt_exist'), 'error')
|
|
return false
|
|
end
|
|
|
|
local employeeGrade = groupType == 'job' and employee.PlayerData.jobs?[groupName] or employee.PlayerData.gangs?[groupName]
|
|
local bossGrade = groupType == 'job' and boss.PlayerData.jobs?[groupName] or boss.PlayerData.gangs?[groupName]
|
|
|
|
if employeeGrade >= bossGrade then
|
|
exports.qbx_core:Notify(boss.PlayerData.source, locale('error.fire_boss'), 'error')
|
|
return false
|
|
end
|
|
|
|
if groupType == 'job' then
|
|
local success, errorResult = exports.qbx_core:RemovePlayerFromJob(employee.PlayerData.citizenid, groupName)
|
|
assert(success, errorResult?.message)
|
|
else
|
|
local success, errorResult = exports.qbx_core:RemovePlayerFromGang(employee.PlayerData.citizenid, groupName)
|
|
assert(success, errorResult?.message)
|
|
end
|
|
|
|
if not employee.Offline then
|
|
local message = groupType == 'gang' and locale('error.you_gang_fired', GANGS[groupName].label) or locale('error.you_job_fired', JOBS[groupName].label)
|
|
exports.qbx_core:Notify(employee.PlayerData.source, message, 'error')
|
|
end
|
|
|
|
logger.log({
|
|
source = boss.PlayerData.source,
|
|
event = 'qbx_management:server:fireEmployee',
|
|
message = locale('logs.fired_employee', employeeCitizenId, groupName, groupType),
|
|
webhook = config.discordWebhook
|
|
})
|
|
|
|
return true
|
|
end
|
|
|
|
-- Callback for firing a player from a given society.
|
|
---@param employee string citizenid of employee to be fired
|
|
---@param groupType GroupType
|
|
lib.callback.register('qbx_management:server:fireEmployee', function(source, employee, groupType)
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
local firedEmployee = exports.qbx_core:GetPlayerByCitizenId(employee) or exports.qbx_core:GetOfflinePlayer(employee)
|
|
local playerFullName = player.PlayerData.charinfo.firstname..' '..player.PlayerData.charinfo.lastname
|
|
local organizationLabel = player.PlayerData[groupType].label
|
|
|
|
if not player.PlayerData[groupType].isboss then return end
|
|
if not firedEmployee then lib.print.error("not able to find player with citizenid", employee) return end
|
|
|
|
local success = fireEmployee(employee, player, player.PlayerData[groupType].name, groupType)
|
|
local employeeFullName = firedEmployee.PlayerData.charinfo.firstname..' '..firedEmployee.PlayerData.charinfo.lastname
|
|
|
|
if success then
|
|
local logArea = groupType == 'gang' and 'Gang' or 'Boss'
|
|
local logType = groupType == 'gang' and locale('error.gang_fired') or locale('error.job_fired')
|
|
exports.qbx_core:Notify(source, logType, 'success')
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:fireEmployee',
|
|
message = locale('logs.fired_employee_success', logArea, playerFullName, employeeFullName, organizationLabel),
|
|
webhook = config.discordWebhook
|
|
})
|
|
else
|
|
exports.qbx_core:Notify(source, locale('error.unable_fire'), 'error')
|
|
end
|
|
end)
|
|
|
|
lib.callback.register('qbx_management:server:getBossMenus', function()
|
|
logger.log({
|
|
source = 'qbx_management',
|
|
event = 'qbx_management:server:getBossMenus',
|
|
message = locale('logs.retrieved_boss_menus'),
|
|
webhook = config.discordWebhook
|
|
})
|
|
return menus
|
|
end)
|
|
|
|
---Creates a boss zone for the specified group
|
|
---@param menuInfo MenuInfo
|
|
local function registerBossMenu(menuInfo)
|
|
menus[#menus + 1] = menuInfo
|
|
TriggerClientEvent('qbx_management:client:bossMenuRegistered', -1, menuInfo)
|
|
logger.log({
|
|
source = 'qbx_management',
|
|
event = 'qbx_management:server:registerBossMenu',
|
|
message = locale('logs.registered_boss_menu', menuInfo.groupName),
|
|
webhook = config.discordWebhook
|
|
})
|
|
end
|
|
|
|
exports('RegisterBossMenu', registerBossMenu)
|
|
|
|
---@param source number
|
|
---@param citizenid string
|
|
---@param job string
|
|
local function doPlayerCheckIn(source, citizenid, job)
|
|
playersClockedIn[source] = { citizenid = citizenid, job = job, time = os.time() }
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:doPlayerCheckIn',
|
|
message = locale('logs.player_checkin', citizenid, job),
|
|
webhook = config.discordWebhook
|
|
})
|
|
end
|
|
|
|
---@param source number
|
|
local function onPlayerUnload(source)
|
|
if playersClockedIn[source] then
|
|
OnPlayerCheckOut(playersClockedIn[source])
|
|
playersClockedIn[source] = nil
|
|
logger.log({
|
|
source = source,
|
|
event = 'qbx_management:server:onPlayerUnload',
|
|
message = locale('logs.player_unload', source),
|
|
webhook = config.discordWebhook
|
|
})
|
|
end
|
|
end
|
|
|
|
---@param source number
|
|
RegisterNetEvent('QBCore:Server:OnPlayerLoaded', function()
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
if player == nil then return end
|
|
if player.PlayerData.job.onduty then
|
|
doPlayerCheckIn(player.PlayerData.source, player.PlayerData.citizenid, player.PlayerData.job.name)
|
|
end
|
|
end)
|
|
|
|
---@param source number
|
|
---@param job table?
|
|
AddEventHandler('QBCore:Server:OnJobUpdate', function(source, job)
|
|
if playersClockedIn[source] then
|
|
onPlayerUnload(source)
|
|
end
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
if player == nil then return end
|
|
if player.PlayerData.job.onduty then
|
|
doPlayerCheckIn(player.PlayerData.source, player.PlayerData.citizenid, job.name)
|
|
end
|
|
end)
|
|
|
|
---@param source number
|
|
---@param duty boolean
|
|
AddEventHandler('QBCore:Server:SetDuty', function(source, duty)
|
|
local player = exports.qbx_core:GetPlayer(source)
|
|
if player == nil then return end
|
|
if duty then
|
|
doPlayerCheckIn(player.PlayerData.source, player.PlayerData.citizenid, player.PlayerData.job.name)
|
|
else
|
|
onPlayerUnload(player.PlayerData.source)
|
|
end
|
|
end)
|
|
|
|
---@param source number
|
|
AddEventHandler('QBCore:Server:OnPlayerUnload', function()
|
|
onPlayerUnload(source)
|
|
end)
|
|
|
|
---@param source number
|
|
AddEventHandler('playerDropped', function()
|
|
onPlayerUnload(source)
|
|
end) |