For the complete documentation index, see llms.txt. This page is also available as Markdown.

editable.lua

if config.ESX.ESXService.active then
    for i = 1, #config.ESX.ESXService.jobs do
        local job = config.ESX.ESXService.jobs[i]
        TriggerEvent('esx_service:activateService', job.name, job.maxInService)
    end
end

if config.ESX.ESXSociety.active then
    for i = 1, # config.ESX.ESXSociety do
        local job = config.ESX.ESXService[i]
        local societyName = ("society_%s"):format(job.name)
        TriggerEvent('esx_society:registerSociety', job, job, societyName, societyName, societyName, { type = 'public' })
    end
end

function playerIsDead(src)
    assert(src, "source is nil in playerIsDead function")
    if config.framework == "esx" then
        local state = Player(src).state
        return state?.dead or state?.isdead or state?.isDead or false
    else
        local metadata = tgiCore.getPlayer(src).PlayerData.metadata
        return metadata.dead or metadata.isdead or metadata.isDead
    end
end

--- @param xPlayer table Player object
--- @return string|nil itemName The handcuff item name the player has, or nil
function getPlayerHandcuffItem(xPlayer)
    for item, _ in pairs(config.handcuffs.items) do
        if tgiCore.getItemByName(xPlayer, item).amount > 0 then
            return item
        end
    end
    return nil
end

function phoneControl(xPlayer)
    return not config.phoneItems:find(function(itemName)
        return tgiCore.getItemByName(xPlayer, itemName).amount > 0
    end) ~= nil
end

---@param jobs string[] | string
---@param xPlayer table
---@return boolean
function hasJob(jobs, xPlayer)
    if type(jobs) == "string" then jobs = { jobs } end

    local jobData = tgiCore.getJob(xPlayer)
    local jobName = jobData.name
    return lib.table.contains(jobs, jobName)
end

RegisterNetEvent("tgiann-policejob:server:syncVehicleDoors")
AddEventHandler("tgiann-policejob:server:syncVehicleDoors", function(netId, lockStatus)
    local src = source

    local xPlayer = tgiCore.getPlayer(src)
    if not xPlayer then return end

    local job = tgiCore.getJob(xPlayer)

    if not isPolice(job.name) then return end

    local vehicle = NetworkGetEntityFromNetworkId(netId)
    if not vehicle then return end

    SetVehicleDoorsLocked(vehicle, lockStatus)
end)

lib.callback.register("tgiann-policejob:departments:weaponRepair", function(source, jobName, key, index)
    local src = source

    local locationData = getLocationData(jobName, key, index)
    if not locationData then return false end

    local xPlayer = tgiCore.getPlayer(src)
    if not xPlayer then return false end
    if not hasJob(jobName, xPlayer) then return false end

    local repaired = false
    local weaponList = {}

    for i = 1, #locationData.weaponList do
        weaponList[locationData.weaponList[i]:lower()] = true
    end

    if config["tgiann-inventory"] then
        local items = exports["tgiann-inventory"]:GetPlayerItems(src)

        for _, item in pairs(items) do
            if item.name and weaponList[item.name:lower()] then
                exports["tgiann-inventory"]:RepairWeapon(src, item.slot, 100)
                repaired = true
            end
        end
    else
        print("Weapon repair is only supported with tgiann-inventory. You can edit the code to make it work with your inventory system (server/editable.lua file).")
    end

    return repaired
end)

--- Called when a prison sentence is given
--- @param src number Source ID of the police officer who issued the fine
--- @param targetSrc number Source ID of the player who received the fine
--- @param data { time: number } time: Prison duration (minutes)
function onFinePrison(src, targetSrc, data)
    if config.jail.active then
        sendToJail(targetSrc, data.time)
    else
        print(src, targetSrc, json.encode(data))
        print("Prison sentence is not supported. You can edit the code to make it work with your server framework (server/editable.lua file onFinePrison function).")
    end
end

--- Called when a money fine is given
--- @param src number Source ID of the police officer who issued the fine
--- @param targetSrc number Source ID of the player who received the fine
--- @param data { amount: number } amount: Fine amount
function onFineMoney(src, targetSrc, data)
    if config.tgiannServer then
        local xPlayer = tgiCore.getPlayer(src)
        if not xPlayer then return end
        local sharedAccountName = "police"

        local invoiceData = {
            sender = xPlayer.PlayerData.citizenid,
            sender_label = sharedAccountName,
            recipient = sharedAccountName,
            recipient_label = sharedAccountName,
            amount = data.amount,
            payments_num = 1,
            payments_period = 7, -- (in days)
            summary = "Summary"
        }
        exports["vivum-billing"]:SendInvoice(targetSrc, invoiceData)
    else
        print(src, targetSrc, json.encode(data))
        print("Money fine is not supported. You can edit the code to make it work with your server framework (server/editable.lua file onFineMoney function).")
    end
end

--- Called when a community service penalty is given
--- @param src number Source ID of the police officer who issued the fine
--- @param targetSrc number Source ID of the player who received the fine
--- @param data { taskCount: number } taskCount: Number of tasks to complete
function onFineCommunityService(src, targetSrc, data)
    if config.communityService.active then
        sendToCommunityService(targetSrc, data.taskCount)
    else
        print(src, targetSrc, json.encode(data))
        print("Community service penalty is not supported. You can edit the code to make it work with your server framework (server/editable.lua file onFineCommunityService function).")
    end
end

RegisterNetEvent("tgiann-policejob:departmant:saveVehicle")
AddEventHandler("tgiann-policejob:departmant:saveVehicle", function(plate, properties)
    local src = source

    local xPlayer = tgiCore.getPlayer(src)
    if not xPlayer then return end

    local job = tgiCore.getJob(xPlayer)
    if not isPolice(job.name) then return end

    if config.framework == "esx" then
        MySQL.update('UPDATE owned_vehicles SET vehicle = ? WHERE plate = ?', {
            json.encode(properties),
            plate
        })
    else
        MySQL.update('UPDATE player_vehicles SET mods = ? WHERE plate = ?', {
            json.encode(properties),
            plate
        })
    end
end)

-- Bell
RegisterNetEvent("tgiann-policejob:departments:bell")
AddEventHandler("tgiann-policejob:departments:bell", function(data)
    local src = source
    local location = config.departments.locations[data.locationIndex]
    if not location or not location.bell?.active then return end

    local xPlayer = tgiCore.getPlayer(src)
    if not xPlayer then return end
    local characterName = tgiCore.getCharacterName(xPlayer)


    local tgiann_policealert = GetResourceState("tgiann-policealert") == "started"
    if tgiann_policealert then
        return exports["tgiann-policealert"]:Alert(src, {
            jobs = { "police" },
            label = t("BELL_MESSAGE", characterName),
            icon = "bell",
            gender = true,
        })
    end

    triggerClientJobEvent('tgiann-policejob:sendChatMessage', location.jobs, {
        sendNotif = true,
        msg = "BELL_NOTIFICATION",
        args = { t("BELL_PREFIX"), t("BELL_MESSAGE", characterName) },
        color = { 255, 200, 0 },
        msgFormatArgs = { characterName },
    })
end)

---@param xPlayer table
---@param key "ishandcuffed"
---@param value any
---@param updateState boolean
function setPlayerMetadata(xPlayer, key, value, updateState)
    if config.framework == "esx" then
        xPlayer.setMeta(key, value)
    elseif config.framework == "qb" then
        xPlayer.setMetaData(key, value)
    end

    if updateState then
        local src = xPlayer.getSource(xPlayer)
        Player(src).state:set(key, value, true)
    end
end

Last updated