local CurrentActionData, handcuffTimer, dragStatus, blipsCops, currentTask = {}, {}, {}, {}, {} local HasAlreadyEnteredMarker, isDead, isHandcuffed, hasAlreadyJoined, playerInService = false, false, false, false, false local LastStation, LastPart, LastPartNum, LastEntity, CurrentAction, CurrentActionMsg dragStatus.isDragged, isInShopMenu = false, false ESX = nil Citizen.CreateThread(function() while ESX == nil do TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) Citizen.Wait(0) end while ESX.GetPlayerData().job == nil do Citizen.Wait(10) end ESX.PlayerData = ESX.GetPlayerData() end) function cleanPlayer(playerPed) SetPedArmour(playerPed, 0) ClearPedBloodDamage(playerPed) ResetPedVisibleDamage(playerPed) ClearPedLastWeaponDamage(playerPed) ResetPedMovementClipset(playerPed, 0) end function setUniform(uniform, playerPed) TriggerEvent('skinchanger:getSkin', function(skin) local uniformObject if skin.sex == 0 then uniformObject = Config.Uniforms[uniform].male else uniformObject = Config.Uniforms[uniform].female end if uniformObject then TriggerEvent('skinchanger:loadClothes', skin, uniformObject) if uniform == 'bullet_wear' then SetPedArmour(playerPed, 100) end else ESX.ShowNotification(_U('no_outfit')) end end) end function OpenCloakroomMenu() local playerPed = PlayerPedId() local grade = ESX.PlayerData.job.grade_name local elements = { {label = _U('citizen_wear'), value = 'citizen_wear'}, {label = _U('bullet_wear'), uniform = 'bullet_wear'}, {label = _U('gilet_wear'), uniform = 'gilet_wear'}, {label = _U('police_wear'), uniform = grade} } if Config.EnableCustomPeds then for k,v in ipairs(Config.CustomPeds.shared) do table.insert(elements, {label = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel}) end for k,v in ipairs(Config.CustomPeds[grade]) do table.insert(elements, {label = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel}) end end ESX.UI.Menu.CloseAll() ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'cloakroom', { title = _U('cloakroom'), align = 'top-left', elements = elements }, function(data, menu) cleanPlayer(playerPed) if data.current.value == 'citizen_wear' then if Config.EnableCustomPeds then ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) local isMale = skin.sex == 0 TriggerEvent('skinchanger:loadDefaultModel', isMale, function() ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) TriggerEvent('skinchanger:loadSkin', skin) TriggerEvent('esx:restoreLoadout') end) end) end) else ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) TriggerEvent('skinchanger:loadSkin', skin) end) end if Config.EnableESXService then ESX.TriggerServerCallback('esx_service:isInService', function(isInService) if isInService then playerInService = false local notification = { title = _U('service_anonunce'), subject = '', msg = _U('service_out_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') TriggerServerEvent('esx_service:disableService', 'police') TriggerEvent('esx_policejob:updateBlip') ESX.ShowNotification(_U('service_out')) end end, 'police') end end if Config.EnableESXService and data.current.value ~= 'citizen_wear' then local awaitService ESX.TriggerServerCallback('esx_service:isInService', function(isInService) if not isInService then if Config.MaxInService == -1 then ESX.TriggerServerCallback('esx_service:enableService', function(canTakeService, maxInService, inServiceCount) if not canTakeService then ESX.ShowNotification(_U('service_max', inServiceCount, maxInService)) else awaitService = true playerInService = true local notification = { title = _U('service_anonunce'), subject = '', msg = _U('service_in_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') TriggerEvent('esx_policejob:updateBlip') ESX.ShowNotification(_U('service_in')) end end, 'police') else awaitService = true playerInService = true local notification = { title = _U('service_anonunce'), subject = '', msg = _U('service_in_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') TriggerEvent('esx_policejob:updateBlip') ESX.ShowNotification(_U('service_in')) end else awaitService = true end end, 'police') while awaitService == nil do Citizen.Wait(5) end -- if we couldn't enter service don't let the player get changed if not awaitService then return end end if data.current.uniform then setUniform(data.current.uniform, playerPed) elseif data.current.value == 'freemode_ped' then local modelHash ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) if skin.sex == 0 then modelHash = GetHashKey(data.current.maleModel) else modelHash = GetHashKey(data.current.femaleModel) end ESX.Streaming.RequestModel(modelHash, function() SetPlayerModel(PlayerId(), modelHash) SetModelAsNoLongerNeeded(modelHash) SetPedDefaultComponentVariation(PlayerPedId()) TriggerEvent('esx:restoreLoadout') end) end) end end, function(data, menu) menu.close() CurrentAction = 'menu_cloakroom' CurrentActionMsg = _U('open_cloackroom') CurrentActionData = {} end) end function OpenArmoryMenu(station) local elements = { {label = _U('buy_weapons'), value = 'buy_weapons'} } if Config.EnableArmoryManagement then table.insert(elements, {label = _U('get_weapon'), value = 'get_weapon'}) table.insert(elements, {label = _U('put_weapon'), value = 'put_weapon'}) table.insert(elements, {label = _U('remove_object'), value = 'get_stock'}) table.insert(elements, {label = _U('deposit_object'), value = 'put_stock'}) end ESX.UI.Menu.CloseAll() ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory', { title = _U('armory'), align = 'top-left', elements = elements }, function(data, menu) if data.current.value == 'get_weapon' then OpenGetWeaponMenu() elseif data.current.value == 'put_weapon' then OpenPutWeaponMenu() elseif data.current.value == 'buy_weapons' then OpenBuyWeaponsMenu() elseif data.current.value == 'put_stock' then OpenPutStocksMenu() elseif data.current.value == 'get_stock' then OpenGetStocksMenu() end end, function(data, menu) menu.close() CurrentAction = 'menu_armory' CurrentActionMsg = _U('open_armory') CurrentActionData = {station = station} end) end function OpenPoliceActionsMenu() ESX.UI.Menu.CloseAll() ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'police_actions', { title = 'Police', align = 'top-left', elements = { {label = _U('citizen_interaction'), value = 'citizen_interaction'}, {label = _U('vehicle_interaction'), value = 'vehicle_interaction'}, {label = _U('object_spawner'), value = 'object_spawner'} }}, function(data, menu) if data.current.value == 'citizen_interaction' then local elements = { {label = _U('id_card'), value = 'identity_card'}, {label = _U('search'), value = 'search'}, {label = _U('handcuff'), value = 'handcuff'}, {label = _U('drag'), value = 'drag'}, {label = _U('put_in_vehicle'), value = 'put_in_vehicle'}, {label = _U('out_the_vehicle'), value = 'out_the_vehicle'}, {label = _U('fine'), value = 'fine'}, {label = _U('unpaid_bills'), value = 'unpaid_bills'} } if Config.EnableLicenses then table.insert(elements, {label = _U('license_check'), value = 'license'}) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { title = _U('citizen_interaction'), align = 'top-left', elements = elements }, function(data2, menu2) local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer ~= -1 and closestDistance <= 3.0 then local action = data2.current.value if action == 'identity_card' then OpenIdentityCardMenu(closestPlayer) elseif action == 'search' then OpenBodySearchMenu(closestPlayer) elseif action == 'handcuff' then TriggerServerEvent('esx_policejob:handcuff', GetPlayerServerId(closestPlayer)) elseif action == 'drag' then TriggerServerEvent('esx_policejob:drag', GetPlayerServerId(closestPlayer)) elseif action == 'put_in_vehicle' then TriggerServerEvent('esx_policejob:putInVehicle', GetPlayerServerId(closestPlayer)) elseif action == 'out_the_vehicle' then TriggerServerEvent('esx_policejob:OutVehicle', GetPlayerServerId(closestPlayer)) elseif action == 'fine' then OpenFineMenu(closestPlayer) elseif action == 'license' then ShowPlayerLicense(closestPlayer) elseif action == 'unpaid_bills' then OpenUnpaidBillsMenu(closestPlayer) end else ESX.ShowNotification(_U('no_players_nearby')) end end, function(data2, menu2) menu2.close() end) elseif data.current.value == 'vehicle_interaction' then local elements = {} local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() if DoesEntityExist(vehicle) then table.insert(elements, {label = _U('vehicle_info'), value = 'vehicle_infos'}) table.insert(elements, {label = _U('pick_lock'), value = 'hijack_vehicle'}) table.insert(elements, {label = _U('impound'), value = 'impound'}) end table.insert(elements, {label = _U('search_database'), value = 'search_database'}) ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_interaction', { title = _U('vehicle_interaction'), align = 'top-left', elements = elements }, function(data2, menu2) local coords = GetEntityCoords(playerPed) vehicle = ESX.Game.GetVehicleInDirection() action = data2.current.value if action == 'search_database' then LookupVehicle() elseif DoesEntityExist(vehicle) then if action == 'vehicle_infos' then local vehicleData = ESX.Game.GetVehicleProperties(vehicle) OpenVehicleInfosMenu(vehicleData) elseif action == 'hijack_vehicle' then if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 3.0) then TaskStartScenarioInPlace(playerPed, 'WORLD_HUMAN_WELDING', 0, true) Citizen.Wait(20000) ClearPedTasksImmediately(playerPed) SetVehicleDoorsLocked(vehicle, 1) SetVehicleDoorsLockedForAllPlayers(vehicle, false) ESX.ShowNotification(_U('vehicle_unlocked')) end elseif action == 'impound' then -- is the script busy? if currentTask.busy then return end ESX.ShowHelpNotification(_U('impound_prompt')) TaskStartScenarioInPlace(playerPed, 'CODE_HUMAN_MEDIC_TEND_TO_DEAD', 0, true) currentTask.busy = true currentTask.task = ESX.SetTimeout(10000, function() ClearPedTasks(playerPed) ImpoundVehicle(vehicle) Citizen.Wait(100) -- sleep the entire script to let stuff sink back to reality end) -- keep track of that vehicle! Citizen.CreateThread(function() while currentTask.busy do Citizen.Wait(1000) vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71) if not DoesEntityExist(vehicle) and currentTask.busy then ESX.ShowNotification(_U('impound_canceled_moved')) ESX.ClearTimeout(currentTask.task) ClearPedTasks(playerPed) currentTask.busy = false break end end end) end else ESX.ShowNotification(_U('no_vehicles_nearby')) end end, function(data2, menu2) menu2.close() end) elseif data.current.value == 'object_spawner' then ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { title = _U('traffic_interaction'), align = 'top-left', elements = { {label = _U('cone'), model = 'prop_roadcone02a'}, {label = _U('barrier'), model = 'prop_barrier_work05'}, {label = _U('spikestrips'), model = 'p_ld_stinger_s'}, {label = _U('box'), model = 'prop_boxpile_07d'}, {label = _U('cash'), model = 'hei_prop_cash_crate_half_full'} }}, function(data2, menu2) local playerPed = PlayerPedId() local coords, forward = GetEntityCoords(playerPed), GetEntityForwardVector(playerPed) local objectCoords = (coords + forward * 1.0) ESX.Game.SpawnObject(data2.current.model, objectCoords, function(obj) SetEntityHeading(obj, GetEntityHeading(playerPed)) PlaceObjectOnGroundProperly(obj) end) end, function(data2, menu2) menu2.close() end) end end, function(data, menu) menu.close() end) end function OpenIdentityCardMenu(player) ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) local elements = { {label = _U('name', data.name)}, {label = _U('job', ('%s - %s'):format(data.job, data.grade))} } if Config.EnableESXIdentity then table.insert(elements, {label = _U('sex', _U(data.sex))}) table.insert(elements, {label = _U('dob', data.dob)}) table.insert(elements, {label = _U('height', data.height)}) end if data.drunk then table.insert(elements, {label = _U('bac', data.drunk)}) end if data.licenses then table.insert(elements, {label = _U('license_label')}) for i=1, #data.licenses, 1 do table.insert(elements, {label = data.licenses[i].label}) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { title = _U('citizen_interaction'), align = 'top-left', elements = elements }, nil, function(data, menu) menu.close() end) end, GetPlayerServerId(player)) end function OpenBodySearchMenu(player) ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) local elements = {} for i=1, #data.accounts, 1 do if data.accounts[i].name == 'black_money' and data.accounts[i].money > 0 then table.insert(elements, { label = _U('confiscate_dirty', ESX.Math.Round(data.accounts[i].money)), value = 'black_money', itemType = 'item_account', amount = data.accounts[i].money }) break end end table.insert(elements, {label = _U('guns_label')}) for i=1, #data.weapons, 1 do table.insert(elements, { label = _U('confiscate_weapon', ESX.GetWeaponLabel(data.weapons[i].name), data.weapons[i].ammo), value = data.weapons[i].name, itemType = 'item_weapon', amount = data.weapons[i].ammo }) end table.insert(elements, {label = _U('inventory_label')}) for i=1, #data.inventory, 1 do if data.inventory[i].count > 0 then table.insert(elements, { label = _U('confiscate_inv', data.inventory[i].count, data.inventory[i].label), value = data.inventory[i].name, itemType = 'item_standard', amount = data.inventory[i].count }) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'body_search', { title = _U('search'), align = 'top-left', elements = elements }, function(data, menu) if data.current.value then TriggerServerEvent('esx_policejob:confiscatePlayerItem', GetPlayerServerId(player), data.current.itemType, data.current.value, data.current.amount) OpenBodySearchMenu(player) end end, function(data, menu) menu.close() end) end, GetPlayerServerId(player)) end function OpenFineMenu(player) ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'fine', { title = _U('fine'), align = 'top-left', elements = { {label = _U('traffic_offense'), value = 0}, {label = _U('minor_offense'), value = 1}, {label = _U('average_offense'), value = 2}, {label = _U('major_offense'), value = 3} }}, function(data, menu) OpenFineCategoryMenu(player, data.current.value) end, function(data, menu) menu.close() end) end function OpenFineCategoryMenu(player, category) ESX.TriggerServerCallback('esx_policejob:getFineList', function(fines) local elements = {} for k,fine in ipairs(fines) do table.insert(elements, { label = ('%s %s'):format(fine.label, _U('armory_item', ESX.Math.GroupDigits(fine.amount))), value = fine.id, amount = fine.amount, fineLabel = fine.label }) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'fine_category', { title = _U('fine'), align = 'top-left', elements = elements }, function(data, menu) menu.close() if Config.EnablePlayerManagement then TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_police', _U('fine_total', data.current.fineLabel), data.current.amount) else TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), '', _U('fine_total', data.current.fineLabel), data.current.amount) end ESX.SetTimeout(300, function() OpenFineCategoryMenu(player, category) end) end, function(data, menu) menu.close() end) end, category) end function LookupVehicle() ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'lookup_vehicle', { title = _U('search_database_title'), }, function(data, menu) local length = string.len(data.value) if not data.value or length < 2 or length > 8 then ESX.ShowNotification(_U('search_database_error_invalid')) else ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) local elements = {{label = _U('plate', retrivedInfo.plate)}} menu.close() if not retrivedInfo.owner then table.insert(elements, {label = _U('owner_unknown')}) else table.insert(elements, {label = _U('owner', retrivedInfo.owner)}) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_infos', { title = _U('vehicle_info'), align = 'top-left', elements = elements }, nil, function(data2, menu2) menu2.close() end) end, data.value) end end, function(data, menu) menu.close() end) end function ShowPlayerLicense(player) local elements = {} ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(playerData) if playerData.licenses then for i=1, #playerData.licenses, 1 do if playerData.licenses[i].label and playerData.licenses[i].type then table.insert(elements, { label = playerData.licenses[i].label, type = playerData.licenses[i].type }) end end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'manage_license', { title = _U('license_revoke'), align = 'top-left', elements = elements, }, function(data, menu) ESX.ShowNotification(_U('licence_you_revoked', data.current.label, playerData.name)) TriggerServerEvent('esx_policejob:message', GetPlayerServerId(player), _U('license_revoked', data.current.label)) TriggerServerEvent('esx_license:removeLicense', GetPlayerServerId(player), data.current.type) ESX.SetTimeout(300, function() ShowPlayerLicense(player) end) end, function(data, menu) menu.close() end) end, GetPlayerServerId(player)) end function OpenUnpaidBillsMenu(player) local elements = {} ESX.TriggerServerCallback('esx_billing:getTargetBills', function(bills) for k,bill in ipairs(bills) do table.insert(elements, { label = ('%s - %s'):format(bill.label, _U('armory_item', ESX.Math.GroupDigits(bill.amount))), billId = bill.id }) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'billing', { title = _U('unpaid_bills'), align = 'top-left', elements = elements }, nil, function(data, menu) menu.close() end) end, GetPlayerServerId(player)) end function OpenVehicleInfosMenu(vehicleData) ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) local elements = {{label = _U('plate', retrivedInfo.plate)}} if not retrivedInfo.owner then table.insert(elements, {label = _U('owner_unknown')}) else table.insert(elements, {label = _U('owner', retrivedInfo.owner)}) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_infos', { title = _U('vehicle_info'), align = 'top-left', elements = elements }, nil, function(data, menu) menu.close() end) end, vehicleData.plate) end function OpenGetWeaponMenu() ESX.TriggerServerCallback('esx_policejob:getArmoryWeapons', function(weapons) local elements = {} for i=1, #weapons, 1 do if weapons[i].count > 0 then table.insert(elements, { label = 'x' .. weapons[i].count .. ' ' .. ESX.GetWeaponLabel(weapons[i].name), value = weapons[i].name }) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_get_weapon', { title = _U('get_weapon_menu'), align = 'top-left', elements = elements }, function(data, menu) menu.close() ESX.TriggerServerCallback('esx_policejob:removeArmoryWeapon', function() OpenGetWeaponMenu() end, data.current.value) end, function(data, menu) menu.close() end) end) end function OpenPutWeaponMenu() local elements = {} local playerPed = PlayerPedId() local weaponList = ESX.GetWeaponList() for i=1, #weaponList, 1 do local weaponHash = GetHashKey(weaponList[i].name) if HasPedGotWeapon(playerPed, weaponHash, false) and weaponList[i].name ~= 'WEAPON_UNARMED' then table.insert(elements, { label = weaponList[i].label, value = weaponList[i].name }) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_put_weapon', { title = _U('put_weapon_menu'), align = 'top-left', elements = elements }, function(data, menu) menu.close() ESX.TriggerServerCallback('esx_policejob:addArmoryWeapon', function() OpenPutWeaponMenu() end, data.current.value, true) end, function(data, menu) menu.close() end) end function OpenBuyWeaponsMenu() local elements = {} local playerPed = PlayerPedId() for k,v in ipairs(Config.AuthorizedWeapons[ESX.PlayerData.job.grade_name]) do local weaponNum, weapon = ESX.GetWeapon(v.weapon) local components, label = {} local hasWeapon = HasPedGotWeapon(playerPed, GetHashKey(v.weapon), false) if v.components then for i=1, #v.components do if v.components[i] then local component = weapon.components[i] local hasComponent = HasPedGotWeaponComponent(playerPed, GetHashKey(v.weapon), component.hash) if hasComponent then label = ('%s: %s'):format(component.label, _U('armory_owned')) else if v.components[i] > 0 then label = ('%s: %s'):format(component.label, _U('armory_item', ESX.Math.GroupDigits(v.components[i]))) else label = ('%s: %s'):format(component.label, _U('armory_free')) end end table.insert(components, { label = label, componentLabel = component.label, hash = component.hash, name = component.name, price = v.components[i], hasComponent = hasComponent, componentNum = i }) end end end if hasWeapon and v.components then label = ('%s: >'):format(weapon.label) elseif hasWeapon and not v.components then label = ('%s: %s'):format(weapon.label, _U('armory_owned')) else if v.price > 0 then label = ('%s: %s'):format(weapon.label, _U('armory_item', ESX.Math.GroupDigits(v.price))) else label = ('%s: %s'):format(weapon.label, _U('armory_free')) end end table.insert(elements, { label = label, weaponLabel = weapon.label, name = weapon.name, components = components, price = v.price, hasWeapon = hasWeapon }) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_buy_weapons', { title = _U('armory_weapontitle'), align = 'top-left', elements = elements }, function(data, menu) if data.current.hasWeapon then if #data.current.components > 0 then OpenWeaponComponentShop(data.current.components, data.current.name, menu) end else ESX.TriggerServerCallback('esx_policejob:buyWeapon', function(bought) if bought then if data.current.price > 0 then ESX.ShowNotification(_U('armory_bought', data.current.weaponLabel, ESX.Math.GroupDigits(data.current.price))) end menu.close() OpenBuyWeaponsMenu() else ESX.ShowNotification(_U('armory_money')) end end, data.current.name, 1) end end, function(data, menu) menu.close() end) end function OpenWeaponComponentShop(components, weaponName, parentShop) ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'armory_buy_weapons_components', { title = _U('armory_componenttitle'), align = 'top-left', elements = components }, function(data, menu) if data.current.hasComponent then ESX.ShowNotification(_U('armory_hascomponent')) else ESX.TriggerServerCallback('esx_policejob:buyWeapon', function(bought) if bought then if data.current.price > 0 then ESX.ShowNotification(_U('armory_bought', data.current.componentLabel, ESX.Math.GroupDigits(data.current.price))) end menu.close() parentShop.close() OpenBuyWeaponsMenu() else ESX.ShowNotification(_U('armory_money')) end end, weaponName, 2, data.current.componentNum) end end, function(data, menu) menu.close() end) end function OpenGetStocksMenu() ESX.TriggerServerCallback('esx_policejob:getStockItems', function(items) local elements = {} for i=1, #items, 1 do table.insert(elements, { label = 'x' .. items[i].count .. ' ' .. items[i].label, value = items[i].name }) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { title = _U('police_stock'), align = 'top-left', elements = elements }, function(data, menu) local itemName = data.current.value ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_get_item_count', { title = _U('quantity') }, function(data2, menu2) local count = tonumber(data2.value) if not count then ESX.ShowNotification(_U('quantity_invalid')) else menu2.close() menu.close() TriggerServerEvent('esx_policejob:getStockItem', itemName, count) Citizen.Wait(300) OpenGetStocksMenu() end end, function(data2, menu2) menu2.close() end) end, function(data, menu) menu.close() end) end) end function OpenPutStocksMenu() ESX.TriggerServerCallback('esx_policejob:getPlayerInventory', function(inventory) local elements = {} for i=1, #inventory.items, 1 do local item = inventory.items[i] if item.count > 0 then table.insert(elements, { label = item.label .. ' x' .. item.count, type = 'item_standard', value = item.name }) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', { title = _U('inventory'), align = 'top-left', elements = elements }, function(data, menu) local itemName = data.current.value ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'stocks_menu_put_item_count', { title = _U('quantity') }, function(data2, menu2) local count = tonumber(data2.value) if not count then ESX.ShowNotification(_U('quantity_invalid')) else menu2.close() menu.close() TriggerServerEvent('esx_policejob:putStockItems', itemName, count) Citizen.Wait(300) OpenPutStocksMenu() end end, function(data2, menu2) menu2.close() end) end, function(data, menu) menu.close() end) end) end RegisterNetEvent('esx:setJob') AddEventHandler('esx:setJob', function(job) ESX.PlayerData.job = job Citizen.Wait(5000) TriggerServerEvent('esx_policejob:forceBlip') end) RegisterNetEvent('esx_phone:loaded') AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts) local specialContact = { name = _U('phone_police'), number = 'police', base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDFGQTJDRkI0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDFGQTJDRkM0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MUZBMkNGOTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MUZBMkNGQTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoW66EYAAAjGSURBVHjapJcLcFTV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' } TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon) end) -- don't show dispatches if the player isn't in service AddEventHandler('esx_phone:cancelMessage', function(dispatchNumber) if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' and ESX.PlayerData.job.name == dispatchNumber then -- if esx_service is enabled if Config.EnableESXService and not playerInService then CancelEvent() end end end) AddEventHandler('esx_policejob:hasEnteredMarker', function(station, part, partNum) if part == 'Cloakroom' then CurrentAction = 'menu_cloakroom' CurrentActionMsg = _U('open_cloackroom') CurrentActionData = {} elseif part == 'Armory' then CurrentAction = 'menu_armory' CurrentActionMsg = _U('open_armory') CurrentActionData = {station = station} elseif part == 'Vehicles' then CurrentAction = 'menu_vehicle_spawner' CurrentActionMsg = _U('garage_prompt') CurrentActionData = {station = station, part = part, partNum = partNum} elseif part == 'Helicopters' then CurrentAction = 'Helicopters' CurrentActionMsg = _U('helicopter_prompt') CurrentActionData = {station = station, part = part, partNum = partNum} elseif part == 'BossActions' then CurrentAction = 'menu_boss_actions' CurrentActionMsg = _U('open_bossmenu') CurrentActionData = {} end end) AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum) if not isInShopMenu then ESX.UI.Menu.CloseAll() end CurrentAction = nil end) AddEventHandler('esx_policejob:hasEnteredEntityZone', function(entity) local playerPed = PlayerPedId() if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' and IsPedOnFoot(playerPed) then CurrentAction = 'remove_entity' CurrentActionMsg = _U('remove_prop') CurrentActionData = {entity = entity} end if GetEntityModel(entity) == GetHashKey('p_ld_stinger_s') then local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) if IsPedInAnyVehicle(playerPed, false) then local vehicle = GetVehiclePedIsIn(playerPed) for i=0, 7, 1 do SetVehicleTyreBurst(vehicle, i, true, 1000) end end end end) AddEventHandler('esx_policejob:hasExitedEntityZone', function(entity) if CurrentAction == 'remove_entity' then CurrentAction = nil end end) RegisterNetEvent('esx_policejob:handcuff') AddEventHandler('esx_policejob:handcuff', function() isHandcuffed = not isHandcuffed local playerPed = PlayerPedId() if isHandcuffed then RequestAnimDict('mp_arresting') while not HasAnimDictLoaded('mp_arresting') do Citizen.Wait(100) end TaskPlayAnim(playerPed, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0) SetEnableHandcuffs(playerPed, true) DisablePlayerFiring(playerPed, true) SetCurrentPedWeapon(playerPed, GetHashKey('WEAPON_UNARMED'), true) -- unarm player SetPedCanPlayGestureAnims(playerPed, false) FreezeEntityPosition(playerPed, true) DisplayRadar(false) if Config.EnableHandcuffTimer then if handcuffTimer.active then ESX.ClearTimeout(handcuffTimer.task) end StartHandcuffTimer() end else if Config.EnableHandcuffTimer and handcuffTimer.active then ESX.ClearTimeout(handcuffTimer.task) end ClearPedSecondaryTask(playerPed) SetEnableHandcuffs(playerPed, false) DisablePlayerFiring(playerPed, false) SetPedCanPlayGestureAnims(playerPed, true) FreezeEntityPosition(playerPed, false) DisplayRadar(true) end end) RegisterNetEvent('esx_policejob:unrestrain') AddEventHandler('esx_policejob:unrestrain', function() if isHandcuffed then local playerPed = PlayerPedId() isHandcuffed = false ClearPedSecondaryTask(playerPed) SetEnableHandcuffs(playerPed, false) DisablePlayerFiring(playerPed, false) SetPedCanPlayGestureAnims(playerPed, true) FreezeEntityPosition(playerPed, false) DisplayRadar(true) -- end timer if Config.EnableHandcuffTimer and handcuffTimer.active then ESX.ClearTimeout(handcuffTimer.task) end end end) RegisterNetEvent('esx_policejob:drag') AddEventHandler('esx_policejob:drag', function(copId) if isHandcuffed then dragStatus.isDragged = not dragStatus.isDragged dragStatus.CopId = copId end end) Citizen.CreateThread(function() local wasDragged while true do Citizen.Wait(0) local playerPed = PlayerPedId() if isHandcuffed and dragStatus.isDragged then local targetPed = GetPlayerPed(GetPlayerFromServerId(dragStatus.CopId)) if DoesEntityExist(targetPed) and IsPedOnFoot(targetPed) and not IsPedDeadOrDying(targetPed, true) then if not wasDragged then AttachEntityToEntity(playerPed, targetPed, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) wasDragged = true else Citizen.Wait(1000) end else wasDragged = false dragStatus.isDragged = false DetachEntity(playerPed, true, false) end elseif wasDragged then wasDragged = false DetachEntity(playerPed, true, false) else Citizen.Wait(500) end end end) RegisterNetEvent('esx_policejob:putInVehicle') AddEventHandler('esx_policejob:putInVehicle', function() if isHandcuffed then local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) if IsAnyVehicleNearPoint(coords, 5.0) then local vehicle = GetClosestVehicle(coords, 5.0, 0, 71) if DoesEntityExist(vehicle) then local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle) for i=maxSeats - 1, 0, -1 do if IsVehicleSeatFree(vehicle, i) then freeSeat = i break end end if freeSeat then TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat) dragStatus.isDragged = false end end end end end) RegisterNetEvent('esx_policejob:OutVehicle') AddEventHandler('esx_policejob:OutVehicle', function() local playerPed = PlayerPedId() if IsPedSittingInAnyVehicle(playerPed) then local vehicle = GetVehiclePedIsIn(playerPed, false) TaskLeaveVehicle(playerPed, vehicle, 64) end end) -- Handcuff Citizen.CreateThread(function() while true do Citizen.Wait(0) local playerPed = PlayerPedId() if isHandcuffed then DisableControlAction(0, 1, true) -- Disable pan DisableControlAction(0, 2, true) -- Disable tilt DisableControlAction(0, 24, true) -- Attack DisableControlAction(0, 257, true) -- Attack 2 DisableControlAction(0, 25, true) -- Aim DisableControlAction(0, 263, true) -- Melee Attack 1 DisableControlAction(0, 32, true) -- W DisableControlAction(0, 34, true) -- A DisableControlAction(0, 31, true) -- S DisableControlAction(0, 30, true) -- D DisableControlAction(0, 45, true) -- Reload DisableControlAction(0, 22, true) -- Jump DisableControlAction(0, 44, true) -- Cover DisableControlAction(0, 37, true) -- Select Weapon DisableControlAction(0, 23, true) -- Also 'enter'? DisableControlAction(0, 288, true) -- Disable phone DisableControlAction(0, 289, true) -- Inventory DisableControlAction(0, 170, true) -- Animations DisableControlAction(0, 167, true) -- Job DisableControlAction(0, 0, true) -- Disable changing view DisableControlAction(0, 26, true) -- Disable looking behind DisableControlAction(0, 73, true) -- Disable clearing animation DisableControlAction(2, 199, true) -- Disable pause screen DisableControlAction(0, 59, true) -- Disable steering in vehicle DisableControlAction(0, 71, true) -- Disable driving forward in vehicle DisableControlAction(0, 72, true) -- Disable reversing in vehicle DisableControlAction(2, 36, true) -- Disable going stealth DisableControlAction(0, 47, true) -- Disable weapon DisableControlAction(0, 264, true) -- Disable melee DisableControlAction(0, 257, true) -- Disable melee DisableControlAction(0, 140, true) -- Disable melee DisableControlAction(0, 141, true) -- Disable melee DisableControlAction(0, 142, true) -- Disable melee DisableControlAction(0, 143, true) -- Disable melee DisableControlAction(0, 75, true) -- Disable exit vehicle DisableControlAction(27, 75, true) -- Disable exit vehicle if IsEntityPlayingAnim(playerPed, 'mp_arresting', 'idle', 3) ~= 1 then ESX.Streaming.RequestAnimDict('mp_arresting', function() TaskPlayAnim(playerPed, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0.0, false, false, false) end) end else Citizen.Wait(500) end end end) -- Create blips Citizen.CreateThread(function() for k,v in pairs(Config.PoliceStations) do local blip = AddBlipForCoord(v.Blip.Coords) SetBlipSprite (blip, v.Blip.Sprite) SetBlipDisplay(blip, v.Blip.Display) SetBlipScale (blip, v.Blip.Scale) SetBlipColour (blip, v.Blip.Colour) SetBlipAsShortRange(blip, true) BeginTextCommandSetBlipName('STRING') AddTextComponentSubstringPlayerName(_U('map_blip')) EndTextCommandSetBlipName(blip) end end) -- Draw markers and more Citizen.CreateThread(function() while true do Citizen.Wait(0) if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local isInMarker, hasExited, letSleep = false, false, true local currentStation, currentPart, currentPartNum for k,v in pairs(Config.PoliceStations) do for i=1, #v.Cloakrooms, 1 do local distance = #(playerCoords - v.Cloakrooms[i]) if distance < Config.DrawDistance then DrawMarker(Config.MarkerType.Cloakrooms, v.Cloakrooms[i], 0.0, 0.0, 0.0, 0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) letSleep = false if distance < Config.MarkerSize.x then isInMarker, currentStation, currentPart, currentPartNum = true, k, 'Cloakroom', i end end end for i=1, #v.Armories, 1 do local distance = #(playerCoords - v.Armories[i]) if distance < Config.DrawDistance then DrawMarker(Config.MarkerType.Armories, v.Armories[i], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) letSleep = false if distance < Config.MarkerSize.x then isInMarker, currentStation, currentPart, currentPartNum = true, k, 'Armory', i end end end for i=1, #v.Vehicles, 1 do local distance = #(playerCoords - v.Vehicles[i].Spawner) if distance < Config.DrawDistance then DrawMarker(Config.MarkerType.Vehicles, v.Vehicles[i].Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) letSleep = false if distance < Config.MarkerSize.x then isInMarker, currentStation, currentPart, currentPartNum = true, k, 'Vehicles', i end end end for i=1, #v.Helicopters, 1 do local distance = #(playerCoords - v.Helicopters[i].Spawner) if distance < Config.DrawDistance then DrawMarker(Config.MarkerType.Helicopters, v.Helicopters[i].Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) letSleep = false if distance < Config.MarkerSize.x then isInMarker, currentStation, currentPart, currentPartNum = true, k, 'Helicopters', i end end end if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == 'boss' then for i=1, #v.BossActions, 1 do local distance = #(playerCoords - v.BossActions[i]) if distance < Config.DrawDistance then DrawMarker(Config.MarkerType.BossActions, v.BossActions[i], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) letSleep = false if distance < Config.MarkerSize.x then isInMarker, currentStation, currentPart, currentPartNum = true, k, 'BossActions', i end end end end end if isInMarker and not HasAlreadyEnteredMarker or (isInMarker and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum)) then if (LastStation and LastPart and LastPartNum) and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum) then TriggerEvent('esx_policejob:hasExitedMarker', LastStation, LastPart, LastPartNum) hasExited = true end HasAlreadyEnteredMarker = true LastStation = currentStation LastPart = currentPart LastPartNum = currentPartNum TriggerEvent('esx_policejob:hasEnteredMarker', currentStation, currentPart, currentPartNum) end if not hasExited and not isInMarker and HasAlreadyEnteredMarker then HasAlreadyEnteredMarker = false TriggerEvent('esx_policejob:hasExitedMarker', LastStation, LastPart, LastPartNum) end if letSleep then Citizen.Wait(500) end else Citizen.Wait(500) end end end) -- Enter / Exit entity zone events Citizen.CreateThread(function() local trackedEntities = { 'prop_roadcone02a', 'prop_barrier_work05', 'p_ld_stinger_s', 'prop_boxpile_07d', 'hei_prop_cash_crate_half_full' } while true do Citizen.Wait(500) local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local closestDistance = -1 local closestEntity = nil for i=1, #trackedEntities, 1 do local object = GetClosestObjectOfType(playerCoords, 3.0, GetHashKey(trackedEntities[i]), false, false, false) if DoesEntityExist(object) then local objCoords = GetEntityCoords(object) local distance = #(playerCoords - objCoords) if closestDistance == -1 or closestDistance > distance then closestDistance = distance closestEntity = object end end end if closestDistance ~= -1 and closestDistance <= 3.0 then if LastEntity ~= closestEntity then TriggerEvent('esx_policejob:hasEnteredEntityZone', closestEntity) LastEntity = closestEntity end else if LastEntity then TriggerEvent('esx_policejob:hasExitedEntityZone', LastEntity) LastEntity = nil end end end end) -- Key Controls Citizen.CreateThread(function() while true do Citizen.Wait(0) if CurrentAction then ESX.ShowHelpNotification(CurrentActionMsg) if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then if CurrentAction == 'menu_cloakroom' then OpenCloakroomMenu() elseif CurrentAction == 'menu_armory' then if not Config.EnableESXService then OpenArmoryMenu(CurrentActionData.station) elseif playerInService then OpenArmoryMenu(CurrentActionData.station) else ESX.ShowNotification(_U('service_not')) end elseif CurrentAction == 'menu_vehicle_spawner' then if not Config.EnableESXService then OpenVehicleSpawnerMenu('car', CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) elseif playerInService then OpenVehicleSpawnerMenu('car', CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) else ESX.ShowNotification(_U('service_not')) end elseif CurrentAction == 'Helicopters' then if not Config.EnableESXService then OpenVehicleSpawnerMenu('helicopter', CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) elseif playerInService then OpenVehicleSpawnerMenu('helicopter', CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) else ESX.ShowNotification(_U('service_not')) end elseif CurrentAction == 'delete_vehicle' then ESX.Game.DeleteVehicle(CurrentActionData.vehicle) elseif CurrentAction == 'menu_boss_actions' then ESX.UI.Menu.CloseAll() TriggerEvent('esx_society:openBossMenu', 'police', function(data, menu) menu.close() CurrentAction = 'menu_boss_actions' CurrentActionMsg = _U('open_bossmenu') CurrentActionData = {} end, { wash = false }) -- disable washing money elseif CurrentAction == 'remove_entity' then DeleteEntity(CurrentActionData.entity) end CurrentAction = nil end end -- CurrentAction end if IsControlJustReleased(0, 167) and not isDead and ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions') then if not Config.EnableESXService then OpenPoliceActionsMenu() elseif playerInService then OpenPoliceActionsMenu() else ESX.ShowNotification(_U('service_not')) end end if IsControlJustReleased(0, 38) and currentTask.busy then ESX.ShowNotification(_U('impound_canceled')) ESX.ClearTimeout(currentTask.task) ClearPedTasks(PlayerPedId()) currentTask.busy = false end end end) -- Create blip for colleagues function createBlip(id) local ped = GetPlayerPed(id) local blip = GetBlipFromEntity(ped) if not DoesBlipExist(blip) then -- Add blip and create head display on player blip = AddBlipForEntity(ped) SetBlipSprite(blip, 1) ShowHeadingIndicatorOnBlip(blip, true) -- Player Blip indicator SetBlipRotation(blip, math.ceil(GetEntityHeading(ped))) -- update rotation SetBlipNameToPlayerName(blip, id) -- update blip name SetBlipScale(blip, 0.85) -- set scale SetBlipAsShortRange(blip, true) table.insert(blipsCops, blip) -- add blip to array so we can remove it later end end RegisterNetEvent('esx_policejob:updateBlip') AddEventHandler('esx_policejob:updateBlip', function() -- Refresh all blips for k, existingBlip in pairs(blipsCops) do RemoveBlip(existingBlip) end -- Clean the blip table blipsCops = {} -- Enable blip? if Config.EnableESXService and not playerInService then return end if not Config.EnableJobBlip then return end -- Is the player a cop? In that case show all the blips for other cops if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then ESX.TriggerServerCallback('esx_society:getOnlinePlayers', function(players) for i=1, #players, 1 do if players[i].job.name == 'police' then local id = GetPlayerFromServerId(players[i].source) if NetworkIsPlayerActive(id) and GetPlayerPed(id) ~= PlayerPedId() then createBlip(id) end end end end) end end) AddEventHandler('playerSpawned', function(spawn) isDead = false TriggerEvent('esx_policejob:unrestrain') if not hasAlreadyJoined then TriggerServerEvent('esx_policejob:spawned') end hasAlreadyJoined = true end) AddEventHandler('esx:onPlayerDeath', function(data) isDead = true end) AddEventHandler('onResourceStop', function(resource) if resource == GetCurrentResourceName() then TriggerEvent('esx_policejob:unrestrain') TriggerEvent('esx_phone:removeSpecialContact', 'police') if Config.EnableESXService then TriggerServerEvent('esx_service:disableService', 'police') end if Config.EnableHandcuffTimer and handcuffTimer.active then ESX.ClearTimeout(handcuffTimer.task) end end end) -- handcuff timer, unrestrain the player after an certain amount of time function StartHandcuffTimer() if Config.EnableHandcuffTimer and handcuffTimer.active then ESX.ClearTimeout(handcuffTimer.task) end handcuffTimer.active = true handcuffTimer.task = ESX.SetTimeout(Config.HandcuffTimer, function() ESX.ShowNotification(_U('unrestrained_timer')) TriggerEvent('esx_policejob:unrestrain') handcuffTimer.active = false end) end -- TODO -- - return to garage if owned -- - message owner that his vehicle has been impounded function ImpoundVehicle(vehicle) --local vehicleName = GetLabelText(GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))) ESX.Game.DeleteVehicle(vehicle) ESX.ShowNotification(_U('impound_successful')) currentTask.busy = false end