pScripts
  • INFORMATION
    • FiveM Asset Escrow System
    • Assets Updates
    • Discord Roles
  • Assets & Guides
    • 👨‍⚖️DOJ Job
      • 👋Installation Guide
      • ⚙️Config Files
      • Client Exports
      • Server Exports
    • 💻DOJ MDT
      • 👋Installation Guide
      • ⚙️Config Files
      • Client Exports
      • Server Exports
    • 🌿Weed Plants
      • 👋Installation Guide
      • ⚙️Config Files
      • Client Exports
      • Server Exports
    • 🚗Car Sale Job
      • 👋Installation Guide
      • ⚙️Config File
      • Client Exports
      • Server Exports
    • 📙Job Core
      • ⚙️Config File
      • Exports
    • 👮Police Job
      • 👋Installation Guide
      • ⚠️Common Issues
      • ⁉️Setup Server
      • ⚙️Config Files
      • Client Exports
        • Bodycam
        • Evidence System
        • Duty GPS
        • Interactions
        • Jail System
        • Police Objects
        • Speed Camera
        • Manage Traffic
        • Misc
      • Server Exports
        • Evidence System
        • Interactions
        • Jail System
        • Misc
    • 💻Police MDT
      • ⁉️Setup Server
      • ⚙️Config File
      • Client Exports
      • Server Exports
      • Dispatch System
    • 🚑Ambulance Job
      • 👋Installation Guide
      • ⁉️Setup Server
      • ⚙️Config Files
      • Client Exports
      • Server Exports
    • 💻Ambulance MDT
      • 👋Installation Guide
      • ⚙️Config File
      • Exports and Events
      • Dispatch System
    • 🛠️Mechanic Job
      • ⚙️Config Files
      • Mileage System
      • Nitro System
      • Lifters System
      • Misc
    • 💻Mechanic MDT
      • ⚙️Config File
      • Exports
      • Dispatch System
      • Licenses System
    • 💵Fleeca Robbery
      • 👋Installation Guide
      • ⚙️Config File
    • ⌚Jewelry Robbery
      • 👋Installation Guide
      • ⚙️Config File
    • 💇Appearance
      • ⚙️Config Files
      • Client Exports
    • 👀Hints
      • Exports
    • 👋Helper
      • Exports
    • 🔧Tuning Menu
      • Exports and Events
      • ⚙️Config Files
    • 🆔Documents
      • ⚙️Config File
      • Exports and Events
    • 📱Phone
      • ⤵️INSTALLATION
      • ⚙️CONFIG FILES
      • 📃FEATURES
      • 📱APPS
      • 📇SIM CARDS
      • 📳NOTIFICATIONS
      • 📨MESSAGES
      • 🚘GARAGES
      • 🪙CRYPTO
      • 🔪DARK CONNECT
      • ⌨️FUNCTIONS
      • 🌎LANGUAGE
      • ⚠️COMMON ISSUES
    • 🪙Casino Games
      • 🎰Slot Machine
      • 🏐Roulette
      • ♣️Poker
    • 💻GCT
      • 📨EXPORTS
    • 💻Civil MDT
      • ⤵️INSTALLATION
      • 📱APPS
      • 🏎️BOOSTING
      • 🏅ACHIEVEMENTS
      • ⚠️COMMON ISSUES
Powered by GitBook
On this page
  1. Assets & Guides
  2. Police Job

Config Files

Main Config
Config = {}

Config.Framework = 'ESX' -- ESX / QB / QBOX
Config.Language = 'en' -- pl / en
Config.Inventory = 'ox_inventory' -- ox_inventory / qb-inventory / ps-inventory / qs-inventory / tgiann-inventory / codem-inventory
Config.Target = 'ox_target' -- ox_target / qb-target
Config.Logs = false -- true / false
Config.Debug = false
Config.Commands = true -- set to false if you want dont want to use commands
Config.OxRadial = true -- enable ox radial menu? (you can edit this in bridge/client)
Config.PoliceMenu = false -- set to true if you want to use F6 OX LIB MENU
Config.PoliceMenuKey = 'F6' -- key to open police menu
Config.PoliceMDT = GetResourceState('piotreq_gpt') ~= 'missing' -- you using our police mdt?

lib.locale(Config.Language or 'en')

Config.SSN = 'id' -- database column for character unique id

Config.Jobs = {
    ['police'] = 0,
    ['sheriff'] = 0
}

Config.OutfitsAccess = { -- permissions for /police_outfit
    ['police'] = 0,
    ['sheriff'] = 0
}

Config.Stations = {
    ['MissionRow'] = {
        blips = {
            {
                sprite = 60, color = 29, scale = 0.95, display = 2,
                label = 'Mission Row LSPD', coords = vector3(437.6986, -982.1099, 30.6904)
            },
            {
                sprite = 72, color = 29, scale = 0.8, display = 2,
                label = 'Police Extras', coords = vector3(426.9231, -1023.2134, 28.8635),
                restricted = {['police'] = 0, ['sheriff'] = 0}
            },
        },
        bells = {
            {
                coords = vector3(445.73, -990.36, 30.75), radius = 0.75,
                jobs = {['police'] = true, ['sheriff'] = true}, -- which jobs will get alert
            }
        },
        trashes = {
            {
                coords = vector3(445.83, -1004.18, 30.5), radius = 0.75,
                allowedJobs = {['police'] = 0, ['sheriff'] = 0}, -- which jobs can access trashes
            }
        },
        bodycams = {
            {
                coords = vector3(460.18, -1005.04, 34.0), radius = 0.75,
                allowedJobs = {['police'] = 0, ['sheriff'] = 0}, -- which jobs can access bodycams
            }
        },
        toggleDuty = { -- coords for duty toggle [ONLY QB AND QBOX!!!!!!]
            {
                coords = vector3(446.19, -991.22, 30.5), radius = 0.75,
                allowedJobs = {['police'] = 0, ['sheriff'] = 0},
            }
        }
    }
}

Config.Shops = {
    ['Armory'] = {
        label = 'Police Armory',
        locations = {
            vector3(449.45, -1006.15, 31.0)
        },
        requiredDuty = false,
        radius = 0.75,
        allowedJobs = {['police'] = 0, ['sheriff'] = 0}, -- which jobs can access shop
        inventory = {
            {name = 'spike_strip', price = 0},
            {name = 'police_diving_suit', price = 0},
            {name = 'tracking_band', price = 0},
            {name = 'fingerprinter', price = 0},
            {name = 'stick_bag', price = 0},
            {name = 'stick', price = 0},
            {name = 'body_cam', price = 0},
            {name = 'gps', price = 0},
            {name = 'camera', price = 0},
            {name = 'radio', price = 0},
            {name = 'handcuffs', price = 0},
            {name = 'vest_normal', price = 10},
            {name = 'vest_strong', price = 100},
            {name = 'ammo-9', price = 5},
            {name = 'ammo-rifle', price = 5},
            {name = 'ammo-shotgun', price = 5},
            {name = 'WEAPON_FLASHLIGHT', price = 100},
            {name = 'WEAPON_NIGHTSTICK', price = 100, metadata = {registered = true, serial = 'POL'}},
            {name = 'WEAPON_COMBATPISTOL', price = 1000, license = 'weapon', grade = 1, metadata = {registered = true, serial = 'POL'}},
            {name = 'WEAPON_STUNGUN', price = 1000, metadata = {registered = true, serial = 'POL'}},
            {name = 'WEAPON_PUMPSHOTGUN', price = 10000, license = 'weapon', grade = 5, metadata = {registered = true, serial = 'POL'}},
            {name = 'WEAPON_CARBINERIFLE', price = 15000, license = 'weapon', grade = 10, metadata = {registered = true, serial = 'POL'}},
        },
    }
}

Config.Wardrobes = {
    ['MissionRow'] = {
        coords = vector3(464.6, -1008.23, 31.0),
        radius = 0.75,
        drawSprite = false,
    }
}

Config.Lockers = {
    ['MissionRow'] = {
        coords = vector3(468.25, -1009.97, 31.0),
        radius = 0.75,
        drawSprite = false,
        options = {
            {
                name = 'MissionRow_Locker', -- stash name and target name ;)
                label = locale('private_locker'),
                icon = 'fa-solid fa-box-open',
                distance = 2,
                groups = Config.Jobs,
                isLocker = true, -- set to false if not locker target
                lockerOwner = false, -- false = shared / true = private
                lockerLabel = locale('private_locker'), -- set only if isLocker
                lockerSlots = 50, lockerWeight = 500000,
                onSelect = function()
                    Inventory.openInventory('stash', 'MissionRow_Locker')
                end,
                canInteract = function()
                    local dutyData = Core.CheckDuty()
                    return dutyData.status == 1
                end
            }
        }
    }
}

Config.Radio = {
    [1] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "LSPD"
    },
    [2] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "LSPD"
    },
    [3] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "LSPD"
    },
    [4] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "SHERIFF"
    },
    [5] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "SHERIFF"
    },
    [6] = {
        jobs = {
            ['police'] = true,
            ['sheriff'] = true,
        },
        label = "SHERIFF"
    },
}

Config.SetUniform = function(job, grade)
    local animDict = lib.requestAnimDict('clothingtie')
    TaskPlayAnim(cache.ped, animDict, 'try_tie_negative_a', 2.0, 2.0, 2000, 49, 0, false, false, false)
    RemoveAnimDict(animDict)
    Citizen.Wait(1500)
    if Config.Framework == 'ESX' then
        TriggerEvent('skinchanger:getSkin', function(skin)
            local uniformObject
            
            sex = (skin.sex == 0) and "male" or "female"
    
            uniformObject = Config.Outfits[job][grade][sex]
    
            if uniformObject then
                ClearPedBloodDamage(cache.ped)
                ResetPedVisibleDamage(cache.ped)
                ClearPedLastWeaponDamage(cache.ped)
    
                TriggerEvent('skinchanger:loadClothes', skin, uniformObject)
            else
                Core.ShowNotification(locale('no_outfit'), 'error')
            end
        end)
    else
        local uniformObject
            
        local playerSex = Core.GetPlayerSex()
        sex = (playerSex == 0) and "male" or "female"

        uniformObject = Config.Outfits[job][grade][sex]

        if uniformObject then
            ClearPedBloodDamage(cache.ped)
            ResetPedVisibleDamage(cache.ped)
            ClearPedLastWeaponDamage(cache.ped)

            TriggerEvent('qb-clothing:client:loadOutfit', {outfitData = uniformObject})
        else
            Core.ShowNotification(locale('no_outfit'), 'error')
        end
    end
end

Config.CameraShowHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:showHelper({
            {
                keys = {'X'},
                label = 'Cancel'
            },
            {
                keys = {'ENTER'},
                label = 'Make Photo'
            },
        })
    else
        lib.showTextUI(locale('camera_helper'))
    end
end

Config.CameraHideHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:hideHelper()
    else
        lib.hideTextUI()
    end
end

Config.CameraAccess = false

-- YOU CAN SET CAMERA ITEM ACCESS FOR EACH JOB
-- Config.CameraAccess = {
--     ['police'] = 0,
--     ['sheriff'] = 0
-- 
Bodycam Config
Config.Bodycam = {}

Config.Bodycam.Prop = {
    isEnabled = true, -- is prop enabled?
    ['male'] = {
        boneIndex = 24818,
        offsetCoords = vector3(0.16683, 0.11320, 0.11986),
        offsetRot = vector3(-14.5023, 82.1910, -164.2206),
    },
    ['female'] = {
        boneIndex = 24818,
        offsetCoords = vector3(0.16683, 0.11320, 0.11986),
        offsetRot = vector3(-14.50232, 82.19109, -164.22066),
    },
}

Config.Bodycam.JobRestricted = true -- if true player can only check bodycams from he's job, if false he can check bodycams from all jobs

Config.Bodycam.OnStartWatching = function()
    -- DO SOMETHING
end

Config.Bodycam.OnStopWatching = function()
    -- DO SOMETHING
end
Interactions Config
Config.Interactions = {
    ['PutMouthTape'] = {
        label = locale('put_mouth_tape'),
        icon = 'fa-solid fa-tape',
        distance = 2,
        items = 'mouthtape',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 5000,
                label = locale('putting_mouth_tape'),
                useWhileDead = false,
                canCancel = true,
                disable = {car = true, move = true, combat = true},
                anim = {dict = 'random@train_tracks', clip = 'idle_e',flag = 1},
            }) then
                TriggerServerEvent('p_policejob/server_interactions/toggleMouthTape', {
                    player = targetId,
                    state = true
                })
            end
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or targetState.carriedBy then return false end
            if targetState.isCuffed and not targetState.mouthTaped then return true end
            return false
        end
    },
    ['RemoveMouthTape'] = {
        label = locale('remove_mouth_tape'),
        icon = 'fa-solid fa-tape',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 5000,
                label = locale('removing_mouth_tape'),
                useWhileDead = false,
                canCancel = true,
                disable = {car = true, move = true, combat = true},
                anim = {dict = 'random@train_tracks', clip = 'idle_e',flag = 1},
            }) then
                TriggerServerEvent('p_policejob/server_interactions/toggleMouthTape', {
                    player = targetId,
                    state = false
                })
            end
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or targetState.carriedBy then return false end
            if targetState.mouthTaped then return true end
            return false
        end
    },
    ['HardCuffPlayer'] = {
        label = locale('hard_cuff_player'),
        icon = 'fa-solid fa-handcuffs',
        distance = 2,
        items = 'handcuffs',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local isInFront = utils.isInFront(entity)
            TriggerServerEvent('p_policejob:HandCuffs', {
                type = 'cuffs', state = true, player = targetId, front = isInFront,
                isHard = true
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or targetState.carriedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not targetState.isCuffed and (Player(targetId).state.isDead or Config.Jobs[playerJob.name] or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3)) then
                return true
            end

            return false
        end
    },
    ['CuffPlayer'] = {
        label = locale('cuff_player'),
        icon = 'fa-solid fa-handcuffs',
        distance = 2,
        items = 'handcuffs',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local isInFront = utils.isInFront(entity)
            TriggerServerEvent('p_policejob:HandCuffs', {
                type = 'cuffs', state = true, player = targetId, front = isInFront
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or targetState.carriedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not targetState.isCuffed and (Player(targetId).state.isDead or Config.Jobs[playerJob.name] or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3)) then
                return true
            end

            return false
        end
    },
    ['UnCuffPlayer'] = {
        label = locale('uncuff_player'),
        icon = 'fa-solid fa-handcuffs',
        distance = 2,
        items = 'handcuffs',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:HandCuffs', {
                type = 'cuffs', state = false, player = targetId
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            if Player(targetId).state.isCuffed and Player(targetId).state.cuffType ~= 'rope' then
                return true
            end

            return false
        end
    },
    ['LockpickHandcuffs'] = {
        label = locale('open_cuffs'),
        icon = 'fa-solid fa-lock-open',
        distance = 2,
        items = 'lockpick',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:interactions:OpenCuffs', {
                player = targetId
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            if Player(targetId).state.isCuffed and Player(targetId).state.cuffType ~= 'rope' then
                return true
            end

            return false
        end
    },
    ['PutPlayerHeadBag'] = {
        label = locale('put_player_headbag'),
        icon = 'fa-solid fa-eye-slash',
        distance = 2,
        items = 'headbag',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob/server_interactions/ToggleHeadBag', {
                state = true, player = targetId
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or targetState.hasHeadBag then
                return false
            end

            if targetState.isCuffed or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    },
    ['TakeOffPlayerHeadBag'] = {
        label = locale('take_off_player_headbag'),
        icon = 'fa-solid fa-eye',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob/server_interactions/ToggleHeadBag', {
                state = false, player = targetId
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy or not targetState.hasHeadBag then
                return false
            end

            return true
        end
    },
    ['ZipPlayer'] = {
        label = locale('zip_player'),
        icon = 'fa-solid fa-handcuffs',
        distance = 2,
        items = 'rope',
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local isInFront = utils.isInFront(entity)
            TriggerServerEvent('p_policejob:HandCuffs', {
                type = 'rope', state = true, player = targetId,
                timer = true, time = 60 * 1000, front = isInFront
            })
            -- if you dont want to auto remove rope after 5 minutes, set timer to false, time is in minutes, 5 minutes default
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not Player(targetId).state.isCuffed and (
                IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) or
                playerJob.name == 'police'
            ) then
                return true
            end

            return false
        end
    },
    ['UnZipPlayer'] = {
        label = locale('unzip_player'),
        icon = 'fa-solid fa-handcuffs',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:HandCuffs', {
                type = 'rope', state = false, player = targetId
            })
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            if Player(targetId).state.isCuffed and Player(targetId).state.cuffType == 'rope' then
                return true
            end

            return false
        end
    },
    ['SearchPlayer'] = {
        label = locale('search_player'),
        icon = 'fa-solid fa-wallet',
        distance = 2,
        onSelect = function(data)
            if lib.progressBar({
                duration = 5500,
                label = locale('searching_player'),
                useWhileDead = false,
                canCancel = true,
                disable = {
                    car = true,
                    move = true,
                    combat = true,
                },
                anim = {
                    dict = 'anim@gangops@facility@servers@bodysearch@',
                    clip = 'player_search' 
                },
            }) then
                local entity = type(data) == 'number' and data or data.entity
                local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
                if 
                Player(targetId).state.isCuffed or
                IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) or
                Core.isPlayerDead(targetId) then
                    Inventory.openInventory('player', targetId)
                end
            end
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            if 
            Player(targetId).state.isCuffed or
            IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) or
            Core.isPlayerDead(targetId) then
                return true
            end

            return false
        end
    },
    ['StartDragPlayer'] = {
        label = locale('start_drag'),
        icon = 'fa-solid fa-people-pulling',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:DragPlayer', {state = true, player = targetId})
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.isCuffed or Core.isPlayerDead(targetId) and not Player(targetId).state.draggedBy then
                return true
            end

            return false
        end
    },
    ['StopDragPlayer'] = {
        label = locale('stop_drag'),
        icon = 'fa-solid fa-people-pulling',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:DragPlayer', {state = false, player = targetId})
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy and Player(targetId).state.draggedBy == cache.serverId then
                return true
            end

            return false
        end
    },
    ['OutFromVehicle'] = { -- dont touch this
        label = locale('out_player'),
        icon = 'fa-solid fa-car',
        distance = 2,
        onSelect = function(data, seat)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(GetPedInVehicleSeat(entity, seat)))
            TriggerServerEvent('p_policejob:OutVehicle', {seat = seat, player = targetId})
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            if not NetworkGetEntityIsNetworked(entity) then return false end

            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(GetPedInVehicleSeat(entity, seat)))
            
            if Player(targetId).state.isCuffed or Core.isPlayerDead(targetId) then
                return true
            end

            return false
        end
    },
    ['PutInVehicle'] = { -- dont touch this
        label = locale('put_player'),
        icon = 'fa-solid fa-car',
        distance = 2,
        onSelect = function(data, seat)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:PutInVehicle', {seat = seat, player = targetId})
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.carryingPlayer then
                return false
            end

            local vehicle, coords = lib.getClosestVehicle(GetEntityCoords(cache.ped), 4.0, false)

            if not vehicle or vehicle == 0 or not IsVehicleSeatFree(vehicle, seat) or not NetworkGetEntityIsNetworked(vehicle) then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))

            local targetState = Player(targetId).state
            if targetState.isCuffed or (targetState.draggedBy and targetState.draggedBy == cache.serverId) or Core.isPlayerDead(targetId) then
                return true
            end

            return false
        end
    },
    ['CheckGunPowder'] = {
        label = locale('check_gun_powder'),
        icon = 'fa-solid fa-gun',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 10000,
                label = locale('checking_gun_powder'),
                useWhileDead = false,
                canCancel = true,
                disable = {
                    car = true,
                    move = true,
                    combat = true
                },
                anim = {
                    dict = 'random@train_tracks',
                    clip = 'idle_e',
                    flag = 1
                },
            }) then
                TriggerServerEvent('p_policejob:CheckGunPowder', targetId)
            end
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not Config.Jobs[playerJob.name] then
                return false
            end

            if Player(targetId).state.isCuffed or Core.isPlayerDead(targetId) or 
            IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    },
    ['GetPlayerBlood'] = {
        label = locale('fetch_blood'),
        icon = 'fa-solid fa-eye-dropper',
        groups = Config.Jobs,
        items = {['stick'] = 1, ['stick_bag'] = 1},
        anyItem = true,
        distance = 2,
        onSelect = function(data)
            if Inventory.getItemCount('stick') < 1 or Inventory.getItemCount('stick_bag') < 1 then
                return Core.ShowNotification(locale('you_need_stick_and_bag'), 'error')
            end

            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 10000,
                label = locale('fetching_blood'),
                useWhileDead = false,
                canCancel = true,
                disable = {
                    car = true,
                    move = true,
                    combat = true
                },
                anim = {
                    dict = 'random@train_tracks',
                    clip = 'idle_e',
                    flag = 1
                },
            }) then
                TriggerServerEvent('p_policejob:GetPlayerBlood', targetId)
            end
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not Config.Jobs[playerJob.name] then
                return false
            end

            if Player(targetId).state.isCuffed or Core.isPlayerDead(targetId) or 
            IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    },
    ['GetPlayerFinger'] = {
        label = locale('fetch_finger_print'),
        icon = 'fa-solid fa-fingerprint',
        groups = Config.Jobs,
        items = 'fingerprinter',
        distance = 2,
        onSelect = function(data)
            if Inventory.getItemCount('fingerprinter') < 1 then
                return Core.ShowNotification(locale('you_need_finger_printer'), 'error')
            end

            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 10000,
                label = locale('fetching_finger_print'),
                useWhileDead = false,
                canCancel = true,
                disable = {
                    car = true,
                    move = true,
                    combat = true
                },
                anim = {
                    dict = 'random@train_tracks',
                    clip = 'idle_e',
                    flag = 1
                },
            }) then
                TriggerServerEvent('p_policejob:GetPlayerFingerPrint', targetId)
            end
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if Player(targetId).state.draggedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not Config.Jobs[playerJob.name] then
                return false
            end

            if Player(targetId).state.isCuffed or Core.isPlayerDead(targetId) or 
            IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    },
    ['SetPlayerBand'] = {
        label = locale('set_gps_band'),
        icon = 'fa-solid fa-hands-bound',
        groups = Config.Band.Jobs,
        items = 'tracking_band',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            if lib.progressBar({
                duration = 10000,
                label = locale('setting_gps_band'),
                useWhileDead = false,
                canCancel = true,
                disable = {
                    car = true,
                    move = true,
                    combat = true
                },
                anim = {
                    dict = 'random@train_tracks',
                    clip = 'idle_e',
                    flag = 1
                },
            }) then
                TriggerServerEvent('p_policejob:SetPlayerBand', {
                    player = targetId,
                    state = true
                })
            end
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy then
                return false
            end

            local playerJob = Core.GetPlayerJob()
            if not Config.Jobs[playerJob.name] then
                return false
            end

            local hasBand = targetState.hasTrackingBand
            if hasBand then
                return false
            end

            if targetState.isCuffed or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    },
    ['RemovePlayerBand'] = {
        label = locale('remove_gps_band'),
        icon = 'fa-solid fa-hands-bound',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local playerJob = Core.GetPlayerJob()
            local bandJob = Config.Band.Jobs[playerJob.name]
            if bandJob and tonumber(playerJob.grade) >= bandJob then
                if lib.progressBar({
                    duration = 10000,
                    label = locale('removing_gps_band'),
                    useWhileDead = false,
                    canCancel = true,
                    disable = {
                        car = true,
                        move = true,
                        combat = true
                    },
                    anim = {
                        dict = 'random@train_tracks',
                        clip = 'idle_e',
                        flag = 1
                    },
                }) then
                    TriggerServerEvent('p_policejob:SetPlayerBand', {
                        player = targetId,
                        state = false
                    })
                end
            else
                TriggerServerEvent('p_policejob:BandAlert', targetId)
                local game = lib.skillCheck(
                    {
                        {areaSize = 30, speedMultiplier = 1.5},
                    },
                    {'1', '2', '3', '4'}
                )

                if game then
                    if lib.progressBar({
                        duration = 10000,
                        label = locale('removing_gps_band'),
                        useWhileDead = false,
                        canCancel = true,
                        disable = {
                            car = true,
                            move = true,
                            combat = true
                        },
                        anim = {
                            dict = 'random@train_tracks',
                            clip = 'idle_e',
                            flag = 1
                        },
                    }) then
                        TriggerServerEvent('p_policejob:SetPlayerBand', {
                            player = targetId,
                            state = false
                        })
                    end
                end
            end
        end,
        canInteract = function(entity, seat)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local targetState = Player(targetId).state
            if targetState.draggedBy then
                return false
            end

            local hasBand = targetState.hasTrackingBand
            if hasBand then
                return true
            end

            return false
        end
    },
    ['PutPlayerInTrunk'] = {
        label = locale('put_player_in_trunk'),
        icon = 'fa-solid fa-car',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob/server_trunks/PutPlayerInTrunk', targetId)
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end
            
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local stateBag = Player(targetId).state
            if stateBag.isCuffed or Core.isPlayerDead(targetId) then
                local vehicle, _ = lib.getClosestVehicle(GetEntityCoords(cache.ped), 3.5, true)
                if vehicle and vehicle ~= 0 then
                    return true
                end
            end

            return false
        end
    },
    ['StartCarryPlayer'] = {
        label = locale('start_carry_player'),
        icon = 'fa-solid fa-hands-holding',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob/server_interactions/StartCarryPlayer', targetId)
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local localState = LocalPlayer.state
            if localState.draggingPlayer or localState.carryingPlayer then
                return false
            end

            local stateBag = Player(targetId).state
            if stateBag.draggedBy then
                return false
            end

            return true
        end
    },
    ['StopCarryPlayer'] = {
        label = locale('stop_carry_player'),
        icon = 'fa-solid fa-hands-holding',
        distance = 2,
        onSelect = function(data)
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob/server_interactions/StopCarryPlayer', targetId)
        end,
        canInteract = function(entity)
            if exports['p_policejob']:inTrunk() then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local stateBag = Player(targetId).state
            if stateBag.carriedBy and stateBag.carriedBy == cache.serverId then
                return true
            end

            return false
        end
    },
    ['SendToJail'] = {
        label = locale('send_to_jail'),
        icon = 'fa-solid fa-hashtag',
        distance = 2,
        groups = Config.Jobs,
        onSelect = function(data)
            local input = lib.inputDialog(locale('send_to_jail'), {
                {type = 'number', label = locale('jail_time'), icon = 'clock', default = 0, min = 0, max = 500, required = false},
                {type = 'number', label = locale('jail_fine'), icon = 'dollar-sign', default = 1, min = 1, required = true},
                {type = 'textarea', label = locale('jail_reason'), icon = 'receipt', required = true}
            })
            if not input then return end
            local entity = type(data) == 'number' and data or data.entity
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            TriggerServerEvent('p_policejob:JailPlayer', {
                player = targetId,
                jail = input[1],
                fine = input[2],
                reason = input[3]
            })
        end,
        canInteract = function(entity)
            if not Config.Jail.EnableJail then return false end
            if Config.PoliceMDT or exports['p_policejob']:inTrunk() then return false end
            local targetId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(entity))
            local stateBag = Player(targetId).state
            if stateBag.isCuffed or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
                return true
            end

            return false
        end
    }
}

Config.CuffsAsItem = true -- set to true if you want to use handcuffs as item (target will be available too)
Config.CuffItemCheck = function(entity, playerId)
    local localState = LocalPlayer.state
    if localState.draggingPlayer or localState.carryingPlayer then
        return false
    end

    local targetState = Player(playerId).state
    if targetState.draggedBy or targetState.carriedBy then
        return false
    end

    if Player(playerId).state.isCuffed then
        return 'uncuff'
    else
        local playerJob = Core.GetPlayerJob()
        if Player(playerId).state.isDead or Config.Jobs[playerJob.name] or IsEntityPlayingAnim(entity, "random@mugging3", "handsup_standing_base", 3) then
            return 'cuff'
        end
    end

    return false
end

Config.Carry = {
    useRequest = true, -- if true other player need to accept carry request
    stopCarryKey = 'E', -- set key to stop carry [FOR EXAMPLE 'E']
    onStartCarrying = function(playerId, role)
        if role == 'carrying' then
            lib.showTextUI('[E] - Stop carry')
        end
    end,
    onStopCarrying = function(playerId, role)
        if role == 'carrying' then
            lib.hideTextUI()
        end
    end,
    onRequest = function(playerId)
        local useAlert = false -- SET TO TRUE IF YOU WANT TO USE ALERT DIALOG
        if not useAlert then
            local result = false
            local timer = 0
            Core.ShowNotification(locale('player_request_carry', playerId))
            while timer < 500 do
                Citizen.Wait(1)
                timer += 1
                if IsControlJustReleased(0, 38) then
                    result = true
                    break
                end
            end
        
            return result
        else
            local alert = lib.alertDialog({
                header = locale('carry_person_request'),
                content = locale('carry_person_request_info', playerId),
                centered = true,
                cancel = true
            })
            return alert == 'confirm'
        end
    end,
    animation = {
        carried = {
            dict = 'nm',
            clip = 'firemans_carry',
            flag = 33,
            offset = {
                coords = vector3(0.25, -0.05, 0.63),
                rotation = vector3(0.25, 0.0, 180.0)
            }
        },
        carrying = {
            dict = 'missfinale_c2mcs_1',
            clip = 'fin_c2_mcs_1_camman',
            flag = 49
        }
    }
}

Config.LockpickCuffs = {
    miniGame = function()
        local game = lib.skillCheck(
            {
                {areaSize = 30, speedMultiplier = 1.5},
                {areaSize = 30, speedMultiplier = 1.5},
                {areaSize = 30, speedMultiplier = 1.5},
                {areaSize = 30, speedMultiplier = 1.5},
                {areaSize = 30, speedMultiplier = 1.5},
            },
            {'1', '2', '3', '4'}
        )
        return game
    end,
    animation = {
        enabled = true,
        dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@',
        clip = 'machinic_loop_mechandplayer',
        flag = 49
    }
}

Config.DisableKeys = {
    ['hardcuff'] = { -- THIS IS ENABLED KEYS WHILE HARD CUFF !!!!!!!!!!!!!!!!!!!!!!!!!
        0, 1, 2, 249
    },
    ['cuff'] = {
        24, 257, 25, 263, 45, 22, 44, 37, 23, 21, 288, 289, 170, 75,
        167, 73, 199, 59, 71, 72, 47, 264, 257, 140, 141, 142, 143
    },
    ['drag'] = {
        24, 257, 25, 263, 45, 22, 44, 37, 23, 21, 288, 289, 170, 75,
        167, 73, 199, 59, 71, 72, 47, 264, 257, 140, 141, 142, 143
    }
}

Config.OnPlayerCuff = function()
    local playerPed = cache.ped
    SetEnableHandcuffs(playerPed, true)
    DisablePlayerFiring(playerPed, true)
    SetCurrentPedWeapon(playerPed, `WEAPON_UNARMED`, true)
    SetPedCanPlayGestureAnims(playerPed, false)
    LocalPlayer.state.invBusy = true
    LocalPlayer.state.invHotkeys = false
    LocalPlayer.state.canUseWeapons = false
    lib.disableRadial(true)
    if GetResourceState('ox_target') == 'started' then
        exports['ox_target']:disableTargeting(true)
    elseif GetResourceState('qb-target') == 'started' then
        exports['qb-target']:AllowTargeting(false)
    end
    if GetResourceState('lb-phone') == 'started' then
        exports["lb-phone"]:ToggleDisabled(true)
    end
end

Config.OnPlayerUnCuff = function()
    local playerPed = cache.ped
    SetEnableHandcuffs(playerPed, false)
    DisablePlayerFiring(playerPed, false)
    SetPedCanPlayGestureAnims(playerPed, true)
    LocalPlayer.state.invBusy = false
    LocalPlayer.state.invHotkeys = true
    LocalPlayer.state.canUseWeapons = true
    lib.disableRadial(false)
    if GetResourceState('ox_target') == 'started' then
        exports['ox_target']:disableTargeting(false)
    elseif GetResourceState('qb-target') == 'started' then
        exports['qb-target']:AllowTargeting(true)
    end
    if GetResourceState('lb-phone') == 'started' then
        exports["lb-phone"]:ToggleDisabled(false)
    end
end

Config.OnStartPlayerDrag = function()
    LocalPlayer.state.invBusy = true
    LocalPlayer.state.invHotkeys = false
    LocalPlayer.state.canUseWeapons = false
    lib.disableRadial(true)
    if GetResourceState('ox_target') == 'started' then
        exports['ox_target']:disableTargeting(true)
    elseif GetResourceState('qb-target') == 'started' then
        exports['qb-target']:AllowTargeting(false)
    end
    if GetResourceState('lb-phone') == 'started' then
        exports["lb-phone"]:ToggleDisabled(true)
    end
end

Config.OnStopPlayerDrag = function()
    LocalPlayer.state.invBusy = false
    LocalPlayer.state.invHotkeys = true
    LocalPlayer.state.canUseWeapons = true
    lib.disableRadial(false)
    if GetResourceState('ox_target') == 'started' then
        exports['ox_target']:disableTargeting(false)
    elseif GetResourceState('qb-target') == 'started' then
        exports['qb-target']:AllowTargeting(true)
    end
    if GetResourceState('lb-phone') == 'started' then
        exports["lb-phone"]:ToggleDisabled(false)
    end
e
GPS Config
Config.GPS = {}

Config.GPS.NeedDuty = true -- true | false (need to be on duty to turn on/off gps?)
Config.GPS.ShortRange = true -- only visible closests blips on minimap
Config.GPS.RefreshRate = 2500 -- 2.5s
Config.GPS.UseCallSign = false -- true (use job call sign setted by /callsign ?) | false

Config.GPS.Jobs = {
    ['police'] = { -- YOU CAN USE GPS FOR DIFFERENT JOBS ALSO (MECHANIC, EMS, ETC)
        color = 63,
        lights = 1,
        display = 'LSPD',
        types = {
            onFoot = {
                color = 63,
                lights = 1,
                sprite = 1,
                scale = 1.1,
                heading = true
            },
            inVeh = {
                color = 63,
                lights = 1,
                sprite = 56,
                scale = 1.1,
                heading = true
            },
            boat = {
                color = 63,
                lights = 1,
                sprite = 427,
                scale = 1.1,
                heading = true
            },
            plane = {
                color = 63,
                lights = 1,
                sprite = 43,
                scale = 1.1,
                heading = true
            },
            heli = {
                color = 63,
                lights = 1,
                sprite = 43,
                scale = 1.1,
                heading = true
            },
            bike = {
                color = 63,
                lights = 1,
                sprite = 1,
                scale = 1.1,
                heading = true
            },
        }
    },
}
Garage Config
Config.Garage = {}

Config.Garage.CreateVehicleKeys = function(plate, model, netId)
    if GetResourceState('p_carkeys') == 'started' then
        TriggerServerEvent('p_carkeys:CreateKeys', plate)
    elseif GetResourceState('wasabi_carlock') == 'started' then
        exports['wasabi_carlock']:GiveKey(plate)
    elseif GetResourceState('qs-vehiclekeys') == 'started' then
        exports['qs-vehiclekeys']:GiveKeys(plate, model, true)
    elseif GetResourceState('tgiann-hotwire') == 'started' then
        exports["tgiann-hotwire"]:GiveKeyPlate(plate, true)
    elseif GetResourceState('qbx_vehiclekeys') == 'started' then
        TriggerEvent('qb-vehiclekeys:client:AddKeys', plate)
    elseif GetResourceState('qb-vehiclekeys') == 'started' then
        TriggerEvent('qb-vehiclekeys:client:AddKeys', plate)
    end
end

Config.Garage.RemoveVehicleKeys = function(plate, model, netId)
    if GetResourceState('p_carkeys') == 'started' then
        TriggerServerEvent('p_carkeys:RemoveKeys', plate)
    elseif GetResourceState('wasabi_carlock') == 'started' then
        exports['wasabi_carlock']:RemoveKey(plate)
    elseif GetResourceState('qs-vehiclekeys') == 'started' then
        exports['qs-vehiclekeys']:RemoveKeys(plate, model)
    elseif GetResourceState('tgiann-hotwire') == 'started' then
        exports["tgiann-hotwire"]:GiveKeyPlate(plate, true)
    elseif GetResourceState('qb-vehiclekeys') == 'started' then
        TriggerEvent('qb-vehiclekeys:client:RemoveKeys', plate)
    elseif GetResourceState('qbx_vehiclekeys') == 'started' then
        TriggerEvent('qb-vehiclekeys:client:RemoveKeys', plate)
    end
end

Config.Garage.CustomLabels = { -- FOR OWNED VEHICLES ONLY
    ['police'] = 'Police Vehicle',
    ['police2'] = 'Police Vehicle 2'
}

Config.Garage.CustomImages = {
    -- ['police'] = 'LINK TO IMAGE', -- set here link to image, it can be fivemanage :)
    -- ['police2'] = 'LINK TO IMAGE',
    -- ['police3'] = 'LINK TO IMAGE',
}

Config.Garage.Garages = {
    ['Mission_Row'] = {
        -- vehicles = { -- UNCOMMENT THIS IF YOU WANT VEHICLE SPAWNER
        --     ['police'] = {
        --         [0] = { -- FROM GRADE 0 CAN TAKE THIS VEHICLES
        --             ['police'] = 'Police Vehicle' -- spawn name and display name
        --         },
        --         [1] = { -- FROM GRADE 1 CAN TAKE THIS VEHICLES
        --             ['police'] = 'Police Vehicle', -- spawn name and display name
        --             ['police2'] = 'Police Vehicle 2' -- spawn name and display name
        --         }
        --     }
        -- },
        ped = {
            model = 's_m_y_cop_01',
            anim = {dict = 'amb@world_human_cop_idles@male@idle_b', clip = 'idle_e'}
        },
        coords = vector4(434.6770, -1029.1232, 28.9886, 0.0),
        allowedJobs = {
            ['police'] = 0,
            ['sheriff'] = 0
        },
        blip = { -- only visible for allowed jobs
            sprite = 357,
            scale = 0.75,
            color = 3,
            label = 'Mission Row Garage'
        },
        spawnPoints = {
            vector4(431.7113, -1027.2172, 28.9471, 179.8748),
            vector4(427.6960, -1027.6909, 28.9821, 182.6840),
            vector4(424.0269, -1028.0519, 29.0469, 184.6641),
            vector4(420.0333, -1028.3597, 29.1166, 186.3764),
            vector4(416.5734, -1028.6340, 29.1769, 185.2027)
        }
    }
}
Extras Config
Config.Extras = {}

Config.Extras.Points = {
    ['Mission_Row'] = {
        coords = vector3(426.8506, -1023.1243, 28.8620),
        allowedJobs = {
            ['police'] = 0, -- job name and grade
            ['sheriff'] = 0
        }
    }
}

Config.Extras.Callsigns = { -- THIS IS READY FOR SEB5A POLICE VEHICLE PACK
    ['cvpi'] = {
        [1] = 10, -- FIRST NUMBER = 10TH VEHICLE MOD IN cvpi VEHICLE MODEL
        [2] = 9, -- SECOND NUMBER = 9TH VEHICLE MOD IN cvpi VEHICLE MODEL
        [3] = 8 -- THIRD NUMBER = 8TH VEHICLE MOD IN cvpi VEHICLE MODEL
    },
    ['emstahoe'] = {
        [1] = 10,
        [2] = 9,
        [3] = 8
    },
    ['polbuffalo4'] = {
        [1] = 8,
        [2] = 9,
        [3] = 10
    },
    ['polgranger2'] = {
        [1] = 8,
        [2] = 9,
        [3] = 10
    },
    ['policeexp'] = {
        [1] = 10,
        [2] = 9,
        [3] = 8
    },
    ['polscout'] = {
        [1] = 8,
        [2] = 9,
        [3] = 10
    },
    ['poltorrence'] = {
        [1] = 8,
        [2] = 9,
        [3] = 10
    },
    ['polvigero'] = {
        [1] = 8,
        [2] = 9,
        [3] = 10
    },
}
Evidences Config
Config.EnableEvidences = true -- true or false

Config.BloodTypes = {
    'A Rh+', 'A Rh-', 'B Rh+', 'B Rh-', '0 Rh+', '0 Rh-'
}

Config.EvidencesRemovers = {
    ['bullet'] = {
        ['towel'] = 1, -- item name and count, set Config.EvidencesRemovers = false if you dont want other players to remove
    },
    ['blood'] = {
        ['towel'] = 1, -- item name and count
    },
    ['finger'] = {
        ['towel'] = 1, -- item name and count
    },
}

Config.EvidencesExpire = {
    ['bullet'] = 60, -- time in minutes
    ['blood'] = 60, -- time in minutes
    ['finger'] = 60, -- time in minutes
    ['powder'] = 10 -- time in minutes
}

Config.Flashlights = {
    [`WEAPON_FLASHLIGHT`] = true
}

Config.WhitelistedWeapons = { -- which weapons will not leave gun powder
    [`WEAPON_STUNGUN`] = 'Stun Gun' -- label
}

Config.HasGloves = function()
    local hasGloves = false
    if Config.Framework == 'ESX' then
        TriggerEvent('skinchanger:getSkin', function(skin)
            if skin.arms >= 16 and skin.arms < 51 then
                hasGloves = true
            end
        end)
    end

    return hasGloves
end

Config.Laboratories = {
    ['MissionRow'] = {
        job = {['police'] = 0},
        coords = vector3(466.94, -1001.67, 34.2),
        stashCoords = vector3(466.94, -1001.67, 34.2),
        radius = 1.0,
        drawSprite = false,
        canInteract = function()
            local dutyData = Core.CheckDuty()
            return dutyData.status ~= 0
        end,
        process = 1 -- time in minutes, how long process will take
    }
}

Config.EvidenceStorages = {
    ['MissionRow'] = {
        job = {['police'] = 0},
        coords = vector3(471.63, -997.26, 34.25),
        radius = 1.0,
        drawSprite = false,
        canInteract = function()
            local dutyData = Core.CheckDuty()
            return dutyData.status ~= 0
        end,
    }
}
Cameras Config
Config.Cameras = {}

Config.Cameras.WatchPoints = {
    ['MissionRow'] = {
        jobs = {['police'] = 0},
        coords = vector3(441.0, -982.0, 30.69),
        requiredDuty = true
    }
}

Config.Cameras.Models = {
    ['prop_cctv_cam_06a'] = 'CCTV Camera 1',
    ['ch_prop_ch_cctv_cam_02a'] = 'CCTV Camera 2',
    ['tr_prop_tr_camhedz_cctv_01a'] = 'CCTV Camera 3',
    ['prop_cctv_cam_02a'] = 'CCTV Camera 4',
    ['prop_cctv_pole_04'] = 'CCTV Camera Pole'
}

Config.Cameras.AllowedGroups = { -- which groups can create cameras
    ['owner'] = true,
    ['admin'] = true
}

Config.Cameras.AllowedJobs = { -- which jobs can create cameras
    ['police'] = 0,
    ['sheriff'] = 0
}

Config.Cameras.ShowHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:showHelper({
            {
                keys = {'X'},
                label = locale('cancel')
            },
            {
                keys = {'<', '>'},
                label = locale('rotate_x')
            },
            {
                keys = {'N', 'M'},
                label = locale('rotate_y')
            },
            {
                keys = {'↑', '↓'},
                label = locale('rotate_z')
            },
            {
                keys = {'E'},
                label = locale('confirm')
            },
        })
    else
        lib.showTextUI('[X] - '..locale('cancel')..' | [< >] - '..locale('rotate_x')..' | [N/M] -'..locale('rotate_y')..' | [↑ ↓] - '..locale('rotate_z')..' | [E] - '..locale('confirm'))
    end
end

Config.Cameras.HideHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:hideHelper()
    else
        lib.hideTextUI()
    end
end

Config.Cameras.OnStartWatching = function()
    lib.showTextUI('[X] - '..locale('stop_watching')..' | [⇆] - '..locale('rotate_left_right')..' | [↓↑] - '..locale('move_up_down'), {
        position = 'bottom-center'
    })
    SetTimecycleModifier('Island_CCTV_ChannelFuzz')
    SetTimecycleModifierStrength(0.25)
end

Config.Cameras.OnStopWatching = function()
    lib.hideTextUI()
    SetTimecycleModifier('default')
    SetTimecycleModifierStrength(1.0)
end
Jail Config
Config.Jail = {}

Config.Jail.EnableJail = true -- enable jail system
Config.Jail.NeedDuty = true -- officer need to be on duty?
Config.Jail.RemoveItems = false -- locker / wipe / false [locker = all items will go to locker, wipe = all items will be removed, false = nothing will happen]
Config.Jail.WhitelistedItems = { -- items that will not be removed [set to false if none]
    ['money'] = true,
}

Config.Jail.Access = {
    ['jail'] = {
        ['owner'] = true,
        ['admin'] = true,
    },
    ['unjail'] = {
        ['owner'] = true,
        ['admin'] = true,
    },
    ['shortjail'] = {
        ['owner'] = true,
        ['admin'] = true,
    }
}

Config.Jail.Outfit = {
    ["male"] = {
        tshirt_1 = 15,  tshirt_2 = 0,
        torso_1 = 345,   torso_2 = 0,
        decals_1 = 0,   decals_2 = 0,
        arms = 0,
        pants_1 = 138,   pants_2 = 0,
        shoes_1 = 132,   shoes_2 = 0,
        helmet_1 = -1,  helmet_2 = 0,
        mask_1 = 0,     mask_2 = 0,
        chain_1 = 0,    chain_2 = 0,
        ears_1 = 2,     ears_2 = 0
    },
    ["female"] = {
        tshirt_1 = 15,  tshirt_2 = 0,
        torso_1 = 338,   torso_2 = 0,
        decals_1 = 0,   decals_2 = 0,
        arms = 44,
        pants_1 = 145,   pants_2 = 0,
        shoes_1 = 137,   shoes_2 = 0,
        helmet_1 = -1,  helmet_2 = 0,
        mask_1 = 0,     mask_2 = 0,
        chain_1 = 0,    chain_2 = 0,
        ears_1 = 2,     ears_2 = 0
    }
}

Config.Jail.ConvertMonths = function(months)
    return math.floor(months * 60) -- month = 1 minute
end

Config.Jail.ConvertMonths_2 = function(time)
    return math.floor(time / 60) -- seconds to month (1 minute)
end

Config.Jail.SetUniform = function()
    if Config.Framework == 'ESX' then
        local uniformObject
            
        local playerSex = Core.GetPlayerSex()
        local sex = nil
        if playerSex == 'm' or playerSex == 0 then
            sex = 'male'
        else
            sex = 'female'
        end

        uniformObject = Config.Jail.Outfit[sex]

        if GetResourceState('illenium-appearance') == 'started' then
            exports['illenium-appearance']:setPedComponents(cache.ped, uniformObject.components)
            exports['illenium-appearance']:setPedProps(cache.ped, uniformObject.props)
        else
            TriggerEvent('skinchanger:getSkin', function(skin)
                if uniformObject then
                    ClearPedBloodDamage(cache.ped)
                    ResetPedVisibleDamage(cache.ped)
                    ClearPedLastWeaponDamage(cache.ped)
                    TriggerEvent('skinchanger:loadClothes', skin, uniformObject)
                end
            end)
        end
    else
        local uniformObject
            
        local playerSex = Core.GetPlayerSex()
        sex = (playerSex == 0) and "male" or "female"

        uniformObject = Config.Jail.Outfit[sex]

        if uniformObject then
            ClearPedBloodDamage(cache.ped)
            ResetPedVisibleDamage(cache.ped)
            ClearPedLastWeaponDamage(cache.ped)

            if GetResourceState('illenium-appearance') == 'started' then
                exports['illenium-appearance']:setPedComponents(cache.ped, uniformObject.components)
                exports['illenium-appearance']:setPedProps(cache.ped, uniformObject.props)
            else
                TriggerEvent('qb-clothing:client:loadOutfit', {outfitData = uniformObject})
            end
        else
            Core.ShowNotification(locale('no_outfit'), 'error')
        end
    end
end

Config.Jail.Zone = {
    jailCoords = vector4(1755.2000, 2492.9490, 45.6513, 212.2371), -- tp here on jail
    unJailCoords = vector4(1846.5839, 2585.7852, 45.6720, 273.4318), -- tp here on ujail
    points = {
        vector3(1851.6860, 2612.5491, 40.6460),
        vector3(1852.1394, 2701.5581, 40.6460),
        vector3(1773.6439, 2767.1697, 40.6460),
        vector3(1648.2583, 2762.4854, 40.6460),
        vector3(1566.2778, 2682.9824, 40.6460),
        vector3(1530.6156, 2586.8628, 40.6460),
        vector3(1537.3165, 2467.2065, 40.6460),
        vector3(1657.2385, 2390.4211, 40.6460),
        vector3(1763.3314, 2406.4651, 40.6460),
        vector3(1827.3147, 2472.8708, 40.6460),
        vector3(1817.7594, 2533.5786, 40.6460),
        vector3(1820.1619, 2567.2734, 40.6460),
        vector3(1852.0808, 2567.8420, 40.6460),
        vector3(1852.4672, 2625.8269, 40.6460)
    },
    thickness = 50
}

Config.Jail.Cutscene = {
    playerPos = vector4(402.915, -996.759, -99.0002, 185.2249),
    cameraPos = { 
        x = 402.9453, y = -998.3599, z = -98.7041, 
        rotationX = -5.4330, rotationY = 0.0, rotationZ = 0.31496
    },
}

Config.Jail.OnPlayerFine = function(playerId, fine, officerName, officerId) -- SERVER SIDE
    -- do something
end

Config.Jail.OnPlayerJailed = function(player, months, fine, officerName, officerId) -- SERVER SIDE
    -- do something
end

Config.Jail.OnPlayerUnJailed = function(player) -- SERVER SIDE
    TriggerClientEvent('p_policejob/jail/clearJob', player)
    if GetResourceState('illenium-appearance') == 'started' then
        TriggerClientEvent('illenium-appearance:client:reloadSkin', player, true)
    else
        if Config.Framework == 'ESX' then
            local xPlayer = ESX.GetPlayerFromId(player)
            local row = MySQL.single.await('SELECT skin FROM users WHERE identifier = ?', {xPlayer.identifier})
            if row and row.skin then
                local plySkin = json.decode(row.skin)
                TriggerClientEvent('skinchanger:loadClothes', player, plySkin, plySkin)
            end
        else
            local QBCore = exports['qb-core']:GetCoreObject()
            local Player = QBCore.Functions.GetPlayer(player)
            local result = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', { Player.PlayerData.citizenid, 1 })
            if result[1] ~= nil then
                TriggerClientEvent("qb-clothes:loadSkin", player, false, result[1].model, result[1].skin)
            else
                TriggerClientEvent("qb-clothes:loadSkin", player, true)
            end
        end
    end
    -- do something
end

Config.Jail.Lockers = {
    ['MissionRow'] = {
        coords = vector3(465.61, -990.98, 27.2),
        radius = 0.75,
        drawSprite = true,
        options = {
            {
                name = 'MissionRow_Jail_Locker',
                label = locale('jail_locker'),
                icon = 'fa-solid fa-id-card',
                distance = 2,
                drawSprite = true,
                groups = {['police'] = 1},
                onSelect = function()
                    OpenPlayerLocker()
                end,
                canInteract = function()
                    local dutyData = Core.CheckDuty()
                    return dutyData.status == 1
                end
            },
            {
                name = 'MissionRow_Evidence_Locker',
                label = locale('evidence_locker'),
                icon = 'fa-solid fa-id-card',
                distance = 2,
                drawSprite = true,
                groups = {['police'] = 1},
                onSelect = function()
                    OpenPlayerEvidence()
                end,
                canInteract = function()
                    local dutyData = Core.CheckDuty()
                    return dutyData.status == 1
                end
            }
        }
    }
}

Config.Jail.PersonalPrisonLocker = {
    coords = vector3(1838.72, 2581.64, 45.89),
    radius = 0.75,
    label = locale('jail_locker'),
    icon = 'fa-solid fa-id-card',
    distance = 2,
    drawSprite = true,
}

Config.Jail.Ped = {
    model = 's_m_y_cop_01',
    anim = {},
    coords = vector4(1755.2795, 2497.3257, 45.6559, 300.7351) -- coords of ped and target
}

Config.Jail.HelpNotify = function(title, text)
    if GetResourceState('p_hints') == 'started' then
        exports['p_hints']:showHintUI({
            title = title,
            text = text,
        })
    else
        lib.showTextUI(text)
    end
end

Config.Jail.HideHelpNotify = function()
    if GetResourceState('p_hints') == 'started' then
        exports['p_hints']:hideHintUI()
    else
        lib.hideTextUI()
    end
end

Config.Jail.Jobs = {
    [locale('laundry')] = {
        [1] = { -- 1ST STEP
            target = {label = locale('take_laundry'), icon = 'fa-solid fa-tshirt'},
            locations = { -- script will select random location from table
                vector3(1591.77, 2549.59, 45.7),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('laundry'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('laundry'), locale('laundry_start_help'))
            end,
            progress = {
                duration = 7500, label = locale('taking_laundry'),
                anim = {scenario = 'PROP_HUMAN_BUM_BIN'},
                disable = {move = true, combat = true, car = true},
            },
            onEnd = function()
                jailJobs.playAnim({
                    animDict = 'anim@heists@box_carry@', animClip = 'idle', flag = 49,
                    propModel = 'v_ind_rc_overallfld', propBone = 28422,
                    propCoords = vector3(0.0, -0.08, -0.17), propRot = vector3(0.0, 0.0, 0.0),
                    disableSprint = true
                })
            end,
        },
        [2] = {
            target = {label = locale('put_laundry'), icon = 'fa-solid fa-tshirt'},
            locations = {
                vector3(1596.92, 2541.54, 45.6), vector3(1596.92, 2540.85, 45.5),
                vector3(1596.96, 2539.45, 45.6), vector3(1588.68, 2538.05, 45.65),
                vector3(1588.68, 2539.41, 45.6), vector3(1588.67, 2540.86, 45.6),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('laundry'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('laundry'), locale('laundry_second_help'))
            end,
            onSelect = function()
                local success = lib.skillCheck({'easy', 'easy', {areaSize = 60, speedMultiplier = 2}, 'easy'}, {'w', 'a', 's', 'd'})
                if success then
                    jailJobs.stopAnim()
                end
                return success
            end,
            progress = {
                duration = 7500, label = locale('making_laundry'),
                anim = {scenario = 'PROP_HUMAN_BUM_BIN'},
                disable = {move = true, combat = true, car = true},
            },
            onEnd = function()
                jailJobs.playAnim({
                    animDict = 'anim@heists@box_carry@', animClip = 'idle', flag = 49,
                    propModel = 'p_overalls_02_s', propBone = 28422,
                    propCoords = vector3(0.0, -0.08, -0.17), propRot = vector3(0.0, 0.0, 0.0),
                    disableSprint = true
                })
            end
        },
        [3] = {
            target = {label = locale('fold_laundry'), icon = 'fa-solid fa-tshirt'},
            locations = {
                vector3(1591.7, 2540.97, 45.6), vector3(1591.78, 2538.66, 45.5),
                vector3(1593.54, 2540.93, 45.6), vector3(1593.91, 2538.61, 45.5),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('laundry'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('laundry'), locale('laundry_finish_help'))
            end,
            months = {min = 10, max = 15}, -- how much months will be removed [random select between min and max]
            onSelect = function()
                local success = lib.skillCheck({'easy', 'easy', {areaSize = 60, speedMultiplier = 2}, 'easy'}, {'w', 'a', 's', 'd'})
                if success then
                    jailJobs.stopAnim()
                end
                return success
            end,
            progress = {
                duration = 7500, label = locale('folding_laundry'),
                anim = {scenario = 'PROP_HUMAN_BUM_BIN'},
                disable = {move = true, combat = true, car = true},
            },
            onEnd = function()
                Config.Jail.HideHelpNotify()
            end
        }
    },
    [locale('woodwork')] = {
        [1] = { -- 1ST STEP
            target = {label = locale('take_wood'), icon = 'fa-solid fa-tree'},
            locations = { -- script will select random location from table
                vector3(1566.62, 2548.06, 46.0), vector3(1567.13, 2550.08, 46.0),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('woodwork'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('woodwork'), locale('woodwork_start_help'))
            end,
            progress = {
                duration = 7500, label = locale('taking_wood'),
                anim = {scenario = 'PROP_HUMAN_BUM_BIN'},
                disable = {move = true, combat = true, car = true},
            },
            onEnd = function()
                jailJobs.playAnim({
                    animDict = 'missfinale_c2mcs_1', animClip = 'fin_c2_mcs_1_camman', flag = 49,
                    propModel = 'bzzz_lumberjack_wood_pack_3a_static', propBone = 6286,
                    -- PROPS CREDITS - https://forum.cfx.re/t/props-woods-for-lumberjack/5119893
                    propCoords = vector3(0.09, 0.1, -0.06), propRot = vector3(6.28, 0.0, 10.64),
                    disableSprint = true
                })
            end,
        },
        [2] = {
            target = {label = locale('process_wood'), icon = 'fa-solid fa-tree'},
            locations = {
                vector3(1570.9, 2550.35, 45.5), vector3(1574.61, 2550.47, 45.5),
                vector3(1570.87, 2545.74, 45.5), vector3(1578.4, 2550.41, 45.6),
                vector3(1574.65, 2545.84, 45.4), vector3(1578.35, 2545.74, 45.5),
                vector3(1581.95, 2550.44, 45.6), vector3(1581.95, 2545.75, 45.6),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('woodwork'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('woodwork'), locale('woodwork_second_help'))
            end,
            onSelect = function()
                local success = lib.skillCheck({'easy', 'easy', {areaSize = 60, speedMultiplier = 2}, 'easy'}, {'w', 'a', 's', 'd'})
                if success then
                    jailJobs.stopAnim()
                end
                return success
            end,
            progress = {
                duration = 7500, label = locale('processing_wood'),
                anim = {dict = 'anim@heists@fleeca_bank@drilling', clip = 'drill_right_end', flag = 1},
                disable = {move = true, combat = true, car = true},
                prop = {model = `prop_tool_consaw`, pos = vec3(0.1, 0.04, 0.35), rot = vec3(5.78, -9.1, -79.23)}
            },
            onEnd = function()
                ClearPedTasks(cache.ped)
                SetTimeout(200, function()
                    jailJobs.playAnim({
                        animDict = 'anim@heists@box_carry@', animClip = 'idle', flag = 49,
                        propModel = 'bzzz_lumberjack_wood_pack_2d', propBone = 28422,
                        propCoords = vector3(0.02, -0.15, -0.17), propRot = vector3(1.3, 0.0, 90.74),
                        disableSprint = true
                    })
                end)
            end
        },
        [3] = {
            target = {label = locale('woodwork_finish'), icon = 'fa-solid fa-tree'},
            locations = { -- script will select random location from table
                vector3(1566.62, 2548.06, 46.0), vector3(1567.13, 2550.08, 46.0),
            },
            blipData = {
                sprite = 514, color = 5, label = locale('woodwork'), scale = 0.8
            },
            onStart = function()
                Config.Jail.HelpNotify(locale('woodwork'), locale('woodwork_finish_help'))
            end,
            months = {min = 2, max = 5}, -- how much months will be removed [random select between min and max]
            onSelect = function()
                local success = lib.skillCheck({'easy', 'easy', {areaSize = 60, speedMultiplier = 2}, 'easy'}, {'w', 'a', 's', 'd'})
                if success then
                    jailJobs.stopAnim()
                end
                return success
            end,
            progress = {
                duration = 7500, label = locale('putting_desks'),
                anim = {scenario = 'PROP_HUMAN_BUM_BIN'},
                disable = {move = true, combat = true, car = true},
            },
            onEnd = function()
                Config.Jail.HideHelpNotify()
            end
        }
    },
}

-- JAIL UTILITIES

Config.Jail.Utils = {}

Config.Jail.Utils.Showers = {
    {coords = vec3(1697.4, 2578.94, 45.4), radius = 0.9, duration = 10000},
    {coords = vec3(1697.26, 2577.38, 45.4), radius = 0.9, duration = 10000},
    {coords = vec3(1697.36, 2575.73, 45.5), radius = 0.9, duration = 10000},
}

Config.Jail.Utils.Undress = function()
    local p = promise.new()
    local firstDict = lib.requestAnimDict('missmic4')
    local secondDict = lib.requestAnimDict('re@construction')
    TaskPlayAnim(cache.ped, firstDict, 'michael_tux_fidget', -8.0, 8.0, 2000, 51)
    if Config.Framework == 'ESX' then
        TriggerEvent('skinchanger:getSkin', function(mySkin)
            Citizen.Wait(500)
            TriggerEvent('skinchanger:loadClothes', mySkin, {
                ['arms'] = 15,
                ['tshirt_1'] = 15, ['tshirt_2'] = 0,
                ['torso_1'] = 15, ['torso_2'] = 0,
                ['bproof_1'] = 0, ['bproof_2'] = 0
            })
            Citizen.Wait(2000)
            TaskPlayAnim(cache.ped, secondDict, 'out_of_breath', -8.0, 8.0, 2000, 51)
            Citizen.Wait(1000)
            TriggerEvent('skinchanger:loadClothes', mySkin, {
                ['arms'] = 15,
                ['pants_1'] = 14, ['pants_2'] = 0,
                ['shoes_1'] = 34, ['shoes_2'] = 0,
                ['tshirt_1'] = 15, ['tshirt_2'] = 0,
                ['torso_1'] = 15, ['torso_2'] = 0,
                ['bproof_1'] = 0, ['bproof_2'] = 0
            })
            ClearPedTasks(cache.ped)
            Citizen.Wait(250)
            p:resolve(mySkin)
        end)
    else
        
    end

    local await = Citizen.Await(p)
    RemoveAnimDict(firstDict)
    RemoveAnimDict(secondDict)
    return await
end

Config.Jail.Utils.Dress = function(playerSkin)
    if Config.Framework == 'ESX' then
        TriggerEvent('skinchanger:loadSkin', playerSkin)
    else
        TriggerServerEvent('qb-clothes:loadPlayerSkin')
    end
end
Mugshot Config
Config.Mugshot = {}

-- REQUIRED TO SCRIPT WORK PROPERLY!
-- https://docs.fivemanage.com/sdk/fivem/install
-- https://docs.fivemanage.com/sdk/fivem/install
-- https://docs.fivemanage.com/sdk/fivem/install
-- https://docs.fivemanage.com/sdk/fivem/install

Config.Mugshot.Points = {
    ['Mission_Row'] = {
        coords = vector3(454.47, -980.56, 27.5),
        photoCoords = vector3(451.0381, -980.3453, 27.8340),
        cameraCoords = vector3(452.9016, -980.3027, 28.3120),
        cameraFov = 40.0,
        jobs = {
            ['police'] = 0
        }
    }
}

Config.Mugshot.SendPhoto = function(data)
    if not data.webhook or data.webhook == '' then
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        print('^8[ERROR] SET WEBHOOK IN CONFIG.WEBHOOKS^7')
        return
    end

    local embeds = {
        {
            ["avatar_url"] = "https://r2.fivemanage.com/xlufCGKYLtGfU8IBmjOL9/360.png",
            ["username"] = "MUGSHOT - LSPD",
            ["author"] = {
                ["name"] = "MUGSHOT",
                ["icon_url"] = "https://r2.fivemanage.com/xlufCGKYLtGfU8IBmjOL9/360.png",
            },
            ["description"] = ('Mugshot ID: **%s**\nSuspect: **%s**\nDOB: **%s**\nOfficer: **%s**\nDescription: **%s**'):format(data.id, data.suspect, data.dob, data.officer, data.description),
            ["type"]="rich",
            ["color"] =5793266,
            ["image"]= {
                ["url"] = data.url
            },
            ["footer"] = {
                ["text"] = os.date(),
                ["icon_url"] = "https://r2.fivemanage.com/xlufCGKYLtGfU8IBmjOL9/360.png",
            },
        }
    }
    PerformHttpRequest(data.webhook, function(err, text, headers) 
    end, 'POST', json.encode({ 
        username = 'MUGSHOT', avatar_url = 'https://r2.fivemanage.com/xlufCGKYLtGfU8IBmjOL9/360.png', embeds = embeds
    }), { ['Content-Type'] = 'application/json' })
end
Objects Config
Config.Objects = {}

Config.Objects.Jobs = {
    ['police'] = {
        ['p_ld_stinger_s'] = locale('stinger'),
        ['prop_consign_01a'] = locale('consign'),
        ['prop_roadcone02a'] = locale('roadcone'),
        ['prop_barrier_work05'] = locale('barrier'),
        ['prop_air_conelight'] = locale('roadcone_light'),
        ['reh_prop_reh_outline_01a'] = locale('tape')
    }
}

Config.Objects.SpikeStripItem = {
    enabled = true, -- IF YOU WANT SPIKE TRIPS AS ITEM, REMOVE MODEL 'p_ld_stinger_s' FROM CONFIG ABOVE
    jobRestricted = true, -- IS ONLY ALLOWED FOR JOBS?
    allowedJobs = Config.Jobs,
    
}

Config.Objects.ShowHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:showHelper({
            {
                keys = {'X'},
                label = locale('cancel')
            },
            {
                keys = {'<', '>'},
                label = locale('rotate_left_right')
            },
            {
                keys = {'E'},
                label = locale('confirm')
            },
        })
    else
        lib.showTextUI('[X] - Cancel | [<] [>] - Rotate | [E] - Confirm')
    end
end

Config.Objects.HideHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:hideHelper()
    else
        lib.hideTextUI()
    end
end

Config.Objects.NeedDuty = true -- need to be on duty to remove props?
Radar Config
Config.Radar = {}

Config.Radar.KeyMapper = 'G' -- Press "G" to toggle Police Radar (SET to "" if you dont want key mapper)

Config.Radar.Unit = 'MPH' -- MPH / KMH

Config.Radar.LockKeys = {
    ['front'] = 'J',
    ['rear'] = 'M'
}

Config.Radar.RestrictedJobs = {
    ['police'] = true,
    ['sheriff'] = true
}

Config.Radar.RestrictedVehicles = {
    [`police`] = true,
    [`police2`] = true,
    [`police3`] = true,
    [`cvpi`] = true
}

Config.Radar.RestrictedDuty = true -- must be on duty to use

Config.HandRadar = {}

Config.HandRadar.RestrictedJobs = { -- which jobs can use
    ['police'] = 0,
    ['sheriff'] = 0
}

Config.HandRadar.RestrictedDuty = true -- must be on duty to use
Radio Config
Config.RadioList = {}

Config.RadioList.Enabled = true -- set to false to disable

Config.RadioList.ToggleKey = 'G' -- KEY TO TOGGLE RADIO LIST [TO DISABLE SET TO FALSE]

Config.RadioList.RestrictedJobs = { -- set to false if you want for everyone
    ['police'] = 0,
    ['sheriff'] = 0,
}

Config.RadioList.ChangePageKeys = {
    ['left'] = 'LEFT', -- left arrow
    ['right'] = 'RIGHT', -- right arrow
}

Config.RadioList.ChannelNames = {
    ['1'] = 'LSPD',
    ['2'] = 'LSPD',
    ['3'] = 'LSPD',
    ['4'] = 'SHERIFF',
    ['5'] = 'SHERIFF'
}

Config.RadioList.TalkingDelay = 50 -- ms [anti spam for radio]

Config.RadioAnimations = {
    {
        label = 'Holding radio',
        animDict = 'anim@male@holding_radio',
        animClip = 'holding_radio_clip',
        animFlag = 50,
        prop = {
            model = 'prop_cs_hand_radio',
            bone = 6286,
            coords = vector3(0.08, 0.03, -0.01),
            rotation = vector3(-59.99, 15.54, -52.55),
        }
    },
    {
        label = 'Fast talk',
        animDict = 'random@arrests',
        animClip = 'generic_radio_chatter',
        animFlag = 50,
        isDefault = true -- default animation [you can set other]
    },
    {
        label = 'Slow talk',
        animDict = 'amb@code_human_police_investigate@idle_a',
        animClip = 'idle_b',
        animFlag = 50,
    }
}

-- https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/ [KEYS HERE
Speedcam Config
Config.Speedcam = {}

Config.Speedcam.AllowedJobs = { -- ALLOWED JOBS TO CREATE SPEED CAMS
    ['police'] = 0,
    ['sheriff'] = 0
}

Config.Speedcam.AllowedGroups = { -- ALLOWED GROUPS TO CREATE SPEED CAMS
    ['owner'] = true,
    ['admin'] = true
}

Config.Speedcam.IgnoredJobs = { -- WHICH JOBS WILL BE IGNORED BY SPEED CAMS
    ['police'] = true,
    ['ambulance'] = true,
    ['sheriff'] = true
}

Config.Speedcam.Models = {
    ['prop_cctv_pole_03'] = 'CCTV Pole 1'
}

Config.Speedcam.Unit = 'KMH' -- KMH / MPH

Config.Speedcam.Blip = {
    sprite = 604,
    color = 0,
    scale = 0.85,
    label = locale('speed_camera')
}

Config.Speedcam.Sound = {
    enabled = true,
    volume = 0.3, -- 0.1 - 1.0
}


Config.Speedcam.ShowHelpNotify = function(title, text)
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:showHelper({
            {
                keys = {'X'},
                label = locale('cancel')
            },
            {
                keys = {'<', '>'},
                label = locale('rotate_left_right')
            },
            {
                keys = {'E'},
                label = locale('confirm')
            },
        })
    else
        lib.showTextUI('[X] - '..locale('cancel')..' | [< >] - '..locale('rotate_left_right')..' | [E] - '..locale('confirm'))
    end
end

Config.Speedcam.HideHelpNotify = function()
    if GetResourceState('p_helper') == 'started' then
        exports['p_helper']:hideHelper()
    else
        lib.hideTextUI()
    end
end

Config.Speedcam.PayFine = function(playerId, totalFine, vehicleSpeed, speedLimit)
    local Player = Core.GetPlayerFromId(playerId)
    if Config.Framework == 'ESX' then
        Player.removeAccountMoney('bank', totalFine)
    else
        Player.Functions.RemoveMoney('bank', totalFine)
    end
    local totalSpeed = math.floor(vehicleSpeed - speedLimit)
    Core.ShowNotification(playerId, locale('you_got_speeding_fine', totalFine, totalSpeed..' '..Config.Speedcam.Unit))

    if Config.Framework == 'ESX' then
        TriggerEvent('esx_addonaccount:getSharedAccount', 'society_police', function(account)
            if account then
                account.addMoney(totalFine)
            end
        end)
    end
end
Tackle Config
Config.Tackle = {}

Config.Tackle.Keys = { -- WHICH KEYS TO PRESS TO TACKLE [ALL AT THE SAME TIME]
    21, -- LEFT SHIT
    38 -- E
}

Config.Tackle.Distance = 3.0 -- distance to tackle someone

Config.Tackle.Timeout = 10000 -- 10 seconds cooldown

Config.Tackle.RestrictedJobs = { -- set to false if you dont want restrict
    ['police'] = 0
}

Config.Tackle.CanUseTackle = function()
    if cache.vehicle and cache.vehicle ~= 0 then
        return false
    end

    if exports['p_policejob']:isTackling() then
        return false
    end

    if IsPedRagdoll(cache.ped) then
        return false
    end
    
    if not IsPedSprinting(cache.ped) then
        return false
    end

    return true
end
Trunks Config
Config.Trunks = {}

Config.Trunks.CameraType = 'dynamic' -- static / dynamic / game

Config.Trunks.CheckVehicleLocks = true -- true = if vehicle is locked player will not be able to get out of trunk

Config.Trunks.CheckTrunkState = true -- true = script will check if trunk is open

Config.Trunks.DefaultOffset = {
    coords = vector3(0.0, 0.85, -0.87),
    rotation = vector3(0.0, 0.0, 40.0)
}

Config.Trunks.Offsets = { -- you can also add manually trunks or use /trunk_editor
    -- ['elegy'] = {
    --     coords = vector3(0.0, -1.70, 0.25),
    --     rotation = vector3(0.0, 0.0, 0.0)
    -- }
}

Config.Trunks.AllowedGroups = {
    ['owner'] = true,
    ['admin'] = true
}

Config.Trunks.ShowHelpNotify = function()
    exports['p_helper']:showHelper({
        {
            keys = {'X'},
            label = 'Cancel'
        },
        {
            keys = {'A', 'D'},
            label = 'Offset X'
        },
        {
            keys = {'N', 'M'},
            label = 'Offset Y'
        },
        {
            keys = {'W', 'S'},
            label = 'Offset Z'
        },
        {
            keys = {'Q', 'R'},
            label = 'Rotation X'
        },
        {
            keys = {'F', 'G'},
            label = 'Rotation Y'
        },
        {
            keys = {'C', 'V'},
            label = 'Rotation Z'
        },
        {
            keys = {'E'},
            label = 'Confirm'
        },
    })
end

Config.Trunks.HideHelpNotify = function()
    exports['p_helper']:hideHelper()
end

Config.Trunks.OnPlayerEnterTrunk = function()
    -- do something
end

Config.Trunks.OnPlayerExitTrunk = function()
    -- do something
en
Vehicleshop Config
Config.VehicleShop = {}

Config.VehicleShop.Enabled = true

Config.VehicleShop.Shops = {
    ['Mission_Row'] = {
        coords = {
            camCoords = vector3(452.4502, -1008.3307, 26.1293),
            vehicleCoords = vector4(446.7827, -1008.3640, 25.9293, 230.3472),
        },
        ped = {
            coords = vector4(459.1993, -998.6849, 25.9292, 178.8984),
            model = 's_f_y_cop_01',
            anim = {dict = 'amb@world_human_cop_idles@male@idle_b', clip = 'idle_e'}
        },
        allowedJobs = {
            ['police'] = { -- vehicles list for specific job
                grade = 0, -- from which grade player can open vehicle shop
                vehicles = {
                    [0] = { -- GRADE 0 CAN BUY THESE VEHICLES
                        ['police'] = 25000,
                    },
                    [1] = { -- GRADE 1 CAN BUY THESE VEHICLES
                        ['police'] = 25000,
                        ['police2'] = 25000,
                    },
                    [2] = { -- GRADE 2 CAN BUY THESE VEHICLES
                        ['police'] = 25000,
                        ['police2'] = 25000,
                        ['police3'] = 25000,
                    },
                    [3] = { -- GRADE 3 CAN BUY THESE VEHICLES
                        ['police'] = 25000,
                        ['police2'] = 25000,
                        ['police3'] = 25000,
                        ['police4'] = 25000,
                    },
                }
            },
            ['sheriff'] = {
                grade = 0,
                vehicles = {
                    [0] = {
                        ['police'] = 25000,
                        ['police2'] = 30000,
                        ['police3'] = 35000
                    },
                    [1] = {
                        ['police'] = 25000,
                        ['police2'] = 30000,
                        ['police3'] = 35000
                    },
                }
            },
        },
        blip = { -- only visible for allowed jobs
            sprite = 357,
            scale = 0.75,
            color = 3,
            label = 'Police Vehicle Shop'
        },
    }
}
Vests Config
Config.Vests = {}

Config.Vests.Items = {
    ['vest_normal'] = {
        armourAmount = 10, -- this item will add 10% to player armout
        maxAmount = 50, -- you can add max 50% from this item
        useable = true, -- if true progress bar will show up
        usingTime = 5000, -- 5 seconds
        usingAnim = {dict = 'clothingshirt', clip = 'try_shirt_positive_d', flag = 49},
        disableControls = {move = false, car = true, combat = true} -- while using item
    },
    ['vest_strong'] = {
        armourAmount = 25, -- this item will add 10% to player armout
        maxAmount = 100, -- you can add max 50% from this item
        useable = true, -- if true progress bar will show up
        usingTime = 5000, -- 5 seconds
        usingAnim = {dict = 'clothingshirt', clip = 'try_shirt_positive_d', flag = 49},
        disableControls = {move = false, car = true, combat = true} -- while using item
    },
}

-- WHEN YOU ADDING NEW ITEM HERE YOU NEED TO CREATE NEW ITEM IN OX_INVENTORY/DATA/ITEMS.LUA LIKE BELOW
-- ['change_item_name'] = {
--     label = 'CHANGE LABEL',
--     weight = 3000,
--     stack = false,
--     consume = 1,
--     client = {
--         export = 'p_policejob.item_name_here' -- CHANGE item_name_here to item name!
--     }
-- },
Webhooks Config
Webhooks = {
    ['band'] = 'WEBHOOK HERE',
    ['bodycam'] = 'WEBHOOK HERE',
    ['divingsuit'] = 'WEBHOOK HERE',
    ['evidence'] = 'WEBHOOK HERE',
    ['gps'] = 'WEBHOOK HERE',
    ['interactions'] = 'WEBHOOK HERE',
    ['jail'] = 'WEBHOOK HERE',
    ['mugshot'] = 'WEBHOOK HERE',
    ['objects'] = 'WEBHOOK HERE',
    ['sounds'] = 'WEBHOOK HERE',
    ['speedcam'] = 'WEBHOOK HERE',
    ['trunks'] = 'WEBHOOK HERE',
}

PreviousSetup ServerNextClient Exports

Last updated 18 days ago

👮
⚙️