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 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 sex = (skin.sex == 0) and "male" or "female" uniformObject = Config.Uniforms[uniform][sex] if uniformObject then TriggerEvent('skinchanger:loadClothes', skin, uniformObject) if uniform == 'bullet_wear' then SetPedArmour(playerPed, 100) end else ESX.ShowNotification(TranslateCap('no_outfit')) end end) end function OpenCloakroomMenu() local playerPed = PlayerPedId() local grade = ESX.PlayerData.job.grade_name local elements = { {unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom")}, {icon = "fas fa-shirt", title = TranslateCap('citizen_wear'), value = 'citizen_wear'}, {icon = "fas fa-shirt", title = TranslateCap('bullet_wear'), uniform = 'bullet_wear'}, {icon = "fas fa-shirt", title = TranslateCap('gilet_wear'), uniform = 'gilet_wear'}, {icon = "fas fa-shirt", title = TranslateCap('police_wear'), uniform = grade} } if Config.EnableCustomPeds then for k,v in ipairs(Config.CustomPeds.shared) do elements[#elements+1] = { icon = "fas fa-shirt", title = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel } end for k,v in ipairs(Config.CustomPeds[grade]) do elements[#elements+1] = { icon = "fas fa-shirt", title = v.label, value = 'freemode_ped', maleModel = v.maleModel, femaleModel = v.femaleModel } end end ESX.OpenContext("right", elements, function(menu,element) cleanPlayer(playerPed) local data = {current = element} 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 = TranslateCap('service_anonunce'), subject = '', msg = TranslateCap('service_out_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') TriggerServerEvent('esx_service:disableService', 'police') ESX.ShowNotification(TranslateCap('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(TranslateCap('service_max', inServiceCount, maxInService)) else awaitService = true playerInService = true local notification = { title = TranslateCap('service_anonunce'), subject = '', msg = TranslateCap('service_in_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') ESX.ShowNotification(TranslateCap('service_in')) end end, 'police') else awaitService = true playerInService = true local notification = { title = TranslateCap('service_anonunce'), subject = '', msg = TranslateCap('service_in_announce', GetPlayerName(PlayerId())), iconType = 1 } TriggerServerEvent('esx_service:notifyAllInService', notification, 'police') ESX.ShowNotification(TranslateCap('service_in')) end else awaitService = true end end, 'police') while awaitService == nil do Wait(0) 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 = joaat(data.current.maleModel) else modelHash = joaat(data.current.femaleModel) end ESX.Streaming.RequestModel(modelHash, function() SetPlayerModel(PlayerId(), modelHash) SetModelAsNoLongerNeeded(modelHash) SetPedDefaultComponentVariation(PlayerPedId()) TriggerEvent('esx:restoreLoadout') end) end) end end, function(menu) CurrentAction = 'menu_cloakroom' CurrentActionMsg = TranslateCap('open_cloackroom') CurrentActionData = {} end) end function OpenArmoryMenu(station) local elements if Config.OxInventory then exports.ox_inventory:openInventory('stash', {id = 'society_police', owner = station}) return ESX.CloseContext() else elements = { {unselectable = true, icon = "fas fa-gun", title = TranslateCap('armory')}, {icon = "fas fa-gun", title = TranslateCap('buy_weapons'), value = 'buy_weapons'} } if Config.EnableArmoryManagement then table.insert(elements, {icon = "fas fa-gun", title = TranslateCap('get_weapon'), value = 'get_weapon'}) table.insert(elements, {icon = "fas fa-gun", title = TranslateCap('put_weapon'), value = 'put_weapon'}) table.insert(elements, {icon = "fas fa-box", title = TranslateCap('remove_object'), value = 'get_stock'}) table.insert(elements, {icon = "fas fa-box", title = TranslateCap('deposit_object'), value = 'put_stock'}) end end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} 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(menu) CurrentAction = 'menu_armory' CurrentActionMsg = TranslateCap('open_armory') CurrentActionData = {station = station} end) end function OpenPoliceActionsMenu() local elements = { {unselectable = true, icon = "fas fa-police", title = TranslateCap('menu_title')}, {icon = "fas fa-user", title = TranslateCap('citizen_interaction'), value = 'citizen_interaction'}, {icon = "fas fa-car", title = TranslateCap('vehicle_interaction'), value = 'vehicle_interaction'}, {icon = "fas fa-object", title = TranslateCap('object_spawner'), value = 'object_spawner'} } ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} if data.current.value == 'citizen_interaction' then local elements2 = { {unselectable = true, icon = "fas fa-user", title = element.title}, {icon = "fas fa-idkyet", title = TranslateCap('id_card'), value = 'identity_card'}, {icon = "fas fa-idkyet", title = TranslateCap('search'), value = 'search'}, {icon = "fas fa-idkyet", title = TranslateCap('handcuff'), value = 'handcuff'}, {icon = "fas fa-idkyet", title = TranslateCap('drag'), value = 'drag'}, {icon = "fas fa-idkyet", title = TranslateCap('put_in_vehicle'), value = 'put_in_vehicle'}, {icon = "fas fa-idkyet", title = TranslateCap('out_the_vehicle'), value = 'out_the_vehicle'}, {icon = "fas fa-idkyet", title = TranslateCap('fine'), value = 'fine'}, {icon = "fas fa-idkyet", title = TranslateCap('unpaid_bills'), value = 'unpaid_bills'} } if Config.EnableLicenses then elements2[#elements2+1] = { icon = "fas fa-scroll", title = TranslateCap('license_check'), value = 'license' } end ESX.OpenContext("right", elements2, function(menu2,element2) local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer ~= -1 and closestDistance <= 3.0 then local data2 = {current = element2} 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(TranslateCap('no_players_nearby')) end end, function(menu) OpenPoliceActionsMenu() end) elseif data.current.value == 'vehicle_interaction' then local elements3 = { {unselectable = true, icon = "fas fa-car", title = element.title} } local playerPed = PlayerPedId() local vehicle = ESX.Game.GetVehicleInDirection() if DoesEntityExist(vehicle) then elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('vehicle_info'), value = 'vehicle_infos'} elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('pick_lock'), value = 'hijack_vehicle'} elements3[#elements3+1] = {icon = "fas fa-car", title = TranslateCap('impound'), value = 'impound'} end elements3[#elements3+1] = { icon = "fas fa-scroll", title = TranslateCap('search_database'), value = 'search_database' } ESX.OpenContext("right", elements3, function(menu3,element3) local data2 = {current = element3} local coords = GetEntityCoords(playerPed) vehicle = ESX.Game.GetVehicleInDirection() action = data2.current.value if action == 'search_database' then LookupVehicle(element3) 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) Wait(20000) ClearPedTasksImmediately(playerPed) SetVehicleDoorsLocked(vehicle, 1) SetVehicleDoorsLockedForAllPlayers(vehicle, false) ESX.ShowNotification(TranslateCap('vehicle_unlocked')) end elseif action == 'impound' then if currentTask.busy then return end ESX.ShowHelpNotification(TranslateCap('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) Wait(100) end) CreateThread(function() while currentTask.busy do Wait(1000) vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71) if not DoesEntityExist(vehicle) and currentTask.busy then ESX.ShowNotification(TranslateCap('impound_canceled_moved')) ESX.ClearTimeout(currentTask.task) ClearPedTasks(playerPed) currentTask.busy = false break end end end) end else ESX.ShowNotification(TranslateCap('no_vehicles_nearby')) end end, function(menu) OpenPoliceActionsMenu() end) elseif data.current.value == "object_spawner" then local elements4 = { {unselectable = true, icon = "fas fa-object", title = element.title}, {icon = "fas fa-cone", title = TranslateCap('cone'), model = 'prop_roadcone02a'}, {icon = "fas fa-cone", title = TranslateCap('barrier'), model = 'prop_barrier_work05'}, {icon = "fas fa-cone", title = TranslateCap('spikestrips'), model = 'p_ld_stinger_s'}, {icon = "fas fa-cone", title = TranslateCap('box'), model = 'prop_boxpile_07d'}, {icon = "fas fa-cone", title = TranslateCap('cash'), model = 'hei_prop_cash_crate_half_full'} } ESX.OpenContext("right", elements4, function(menu4,element4) local data2 = {current = element4} 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) Wait(100) SetEntityHeading(obj, GetEntityHeading(playerPed)) PlaceObjectOnGroundProperly(obj) end) end, function(menu) OpenPoliceActionsMenu() end) end end) end function OpenIdentityCardMenu(player) ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) local elements = { {icon = "fas fa-user", title = TranslateCap('name', data.name)}, {icon = "fas fa-user", title = TranslateCap('job', ('%s - %s'):format(data.job, data.grade))} } if Config.EnableESXIdentity then elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('sex', TranslateCap(data.sex))} elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('dob', data.dob)} elements[#elements+1] = {icon = "fas fa-user", title = TranslateCap('height', data.height)} end if Config.EnableESXOptionalneeds and data.drunk then elements[#elements+1] = {title = TranslateCap('bac', data.drunk)} end if data.licenses then elements[#elements+1] = {title = TranslateCap('license_label')} for i=1, #data.licenses, 1 do elements[#elements+1] = {title = data.licenses[i].label} end end ESX.OpenContext("right", elements, nil, function(menu) OpenPoliceActionsMenu() end) end, GetPlayerServerId(player)) end function OpenBodySearchMenu(player) if Config.OxInventory then ESX.CloseContext() exports.ox_inventory:openInventory('player', GetPlayerServerId(player)) return end ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) local elements = { {unselectable = true, icon = "fas fa-user", title = TranslateCap('search')} } for i=1, #data.accounts, 1 do if data.accounts[i].name == 'black_money' and data.accounts[i].money > 0 then elements[#elements+1] = { icon = "fas fa-money", title = TranslateCap('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 = TranslateCap('guns_label')}) for i=1, #data.weapons, 1 do elements[#elements+1] = { icon = "fas fa-gun", title = TranslateCap('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 elements[#elements+1] = {title = TranslateCap('inventory_label')} for i=1, #data.inventory, 1 do if data.inventory[i].count > 0 then elements[#elements+1] = { icon = "fas fa-box", title = TranslateCap('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.OpenContext("right", elements, function(menu,element) local data = {current = element} if data.current.value then TriggerServerEvent('esx_policejob:confiscatePlayerItem', GetPlayerServerId(player), data.current.itemType, data.current.value, data.current.amount) OpenBodySearchMenu(player) end end) end, GetPlayerServerId(player)) end function OpenFineMenu(player) if Config.EnableFinePresets then local elements = { {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('fine')}, {icon = "fas fa-scroll", title = TranslateCap('traffic_offense'), value = 0}, {icon = "fas fa-scroll", title = TranslateCap('minor_offense'), value = 1}, {icon = "fas fa-scroll", title = TranslateCap('average_offense'), value = 2}, {icon = "fas fa-scroll", title = TranslateCap('major_offense'), value = 3} } ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} OpenFineCategoryMenu(player, data.current.value) end) else ESX.CloseContext() ESX.CloseContext() OpenFineTextInput(player) end end local fineList = {} function OpenFineCategoryMenu(player, category) if not fineList[category] then local p = promise.new() ESX.TriggerServerCallback('esx_policejob:getFineList', function(fines) p:resolve(fines) end, category) fineList[category] = Citizen.Await(p) end local elements = { {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('fine')} } for k,fine in ipairs(fineList[category]) do elements[#elements+1] = { icon = "fas fa-scroll", title = ('%s %s'):format(fine.label, TranslateCap('armory_item', ESX.Math.GroupDigits(fine.amount))), value = fine.id, amount = fine.amount, fineLabel = fine.label } end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} if Config.EnablePlayerManagement then TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_police', TranslateCap('fine_total', data.current.fineLabel), data.current.amount) else TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), '', TranslateCap('fine_total', data.current.fineLabel), data.current.amount) end ESX.SetTimeout(300, function() OpenFineCategoryMenu(player, category) end) end) end function OpenFineTextInput(player) Citizen.CreateThread(function() local amount = 0 local reason = '' AddTextEntry('FMMC_KEY_TIP1', TranslateCap('fine_enter_amount')) Citizen.Wait(0) DisplayOnscreenKeyboard(1, 'FMMC_KEY_TIP1', '', '', '', '', '', 30) while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do Citizen.Wait(0) end if UpdateOnscreenKeyboard() ~= 2 then amount = tonumber(GetOnscreenKeyboardResult()) if amount == nil or amount <= 0 then ESX.ShowNotification(TranslateCap('invalid_amount')) return end end AddTextEntry('FMMC_KEY_TIP1', TranslateCap('fine_enter_text')) Citizen.Wait(0) DisplayOnscreenKeyboard(1, 'FMMC_KEY_TIP1', '', '', '', '', '', 120) while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do Citizen.Wait(0) end if UpdateOnscreenKeyboard() ~= 2 then reason = GetOnscreenKeyboardResult() end Citizen.Wait(500) TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_police', reason, amount) OpenPoliceActionsMenu() end) end function LookupVehicle(elementF) local elements = { {unselectable = true, icon = "fas fa-car", title = elementF.title}, {title = TranslateCap('search_plate'), input = true, inputType = "text", inputPlaceholder = "ABC 123"}, {icon = "fas fa-check-double", title = TranslateCap('lookup_plate'), value = "lookup"} } ESX.OpenContext("right", elements, function(menu,element) local data = {value = menu.eles[2].inputValue} local length = string.len(data.value) if not data.value or length < 2 or length > 8 then ESX.ShowNotification(TranslateCap('search_database_error_invalid')) else ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) local elements = { {unselectable = true, icon = "fas fa-car", title = element.title}, {unselectable = true, icon = "fas fa-car", title = TranslateCap('plate', retrivedInfo.plate)} } if not retrivedInfo.owner then elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner_unknown')} else elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner', retrivedInfo.owner)} end ESX.OpenContext("right", elements, nil, function(menu) OpenPoliceActionsMenu() end) end, data.value) end end) end function ShowPlayerLicense(player) local elements = { {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('license_revoke')} } 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 elements[#elements+1] = { icon = "fas fa-scroll", title = playerData.licenses[i].label, type = playerData.licenses[i].type } end end end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} ESX.ShowNotification(TranslateCap('licence_you_revoked', data.current.label, playerData.name)) TriggerServerEvent('esx_policejob:message', GetPlayerServerId(player), TranslateCap('license_revoked', data.current.label)) TriggerServerEvent('esx_license:removeLicense', GetPlayerServerId(player), data.current.type) ESX.SetTimeout(300, function() ShowPlayerLicense(player) end) end) end, GetPlayerServerId(player)) end function OpenUnpaidBillsMenu(player) local elements = { {unselectable = true, icon = "fas fa-scroll", title = TranslateCap('unpaid_bills')} } ESX.TriggerServerCallback('esx_billing:getTargetBills', function(bills) for k,bill in ipairs(bills) do elements[#elements+1] = { unselectable = true, icon = "fas fa-scroll", title = ('%s - %s'):format(bill.label, TranslateCap('armory_item', ESX.Math.GroupDigits(bill.amount))), billId = bill.id } end ESX.OpenContext("right", elements, nil, nil) end, GetPlayerServerId(player)) end function OpenVehicleInfosMenu(vehicleData) ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(retrivedInfo) local elements = { {unselectable = true, icon = "fas fa-car", title = TranslateCap('vehicle_info')}, {icon = "fas fa-car", title = TranslateCap('plate', retrivedInfo.plate)} } if not retrivedInfo.owner then elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner_unknown')} else elements[#elements+1] = {unselectable = true, icon = "fas fa-user", title = TranslateCap('owner', retrivedInfo.owner)} end ESX.OpenContext("right", elements, nil, nil) end, vehicleData.plate) end function OpenGetWeaponMenu() ESX.TriggerServerCallback('esx_policejob:getArmoryWeapons', function(weapons) local elements = { {unselectable = true, icon = "fas fa-gun", title = TranslateCap('get_weapon_menu')} } for i=1, #weapons, 1 do if weapons[i].count > 0 then elements[#elements+1] = { icon = "fas fa-gun", title = 'x' .. weapons[i].count .. ' ' .. ESX.GetWeaponLabel(weapons[i].name), value = weapons[i].name } end end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} ESX.TriggerServerCallback('esx_policejob:removeArmoryWeapon', function() ESX.CloseContext() OpenGetWeaponMenu() end, data.current.value) end) end) end function OpenPutWeaponMenu() local elements = { {unselectable = true, icon = "fas fa-gun", title = TranslateCap('put_weapon_menu')} } local playerPed = PlayerPedId() local weaponList = ESX.GetWeaponList() for i=1, #weaponList, 1 do local weaponHash = joaat(weaponList[i].name) if HasPedGotWeapon(playerPed, weaponHash, false) and weaponList[i].name ~= 'WEAPON_UNARMED' then elements[#elements+1] = { icon = "fas fa-gun", title = weaponList[i].label, value = weaponList[i].name } end end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} ESX.TriggerServerCallback('esx_policejob:addArmoryWeapon', function() ESX.CloseContext() OpenPutWeaponMenu() end, data.current.value, true) end) end function OpenBuyWeaponsMenu() local elements = { {unselectable = true, icon = "fas fa-gun", title = TranslateCap('armory_weapontitle')} } 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, joaat(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, joaat(v.weapon), component.hash) if hasComponent then label = ('%s: %s'):format(component.label, TranslateCap('armory_owned')) else if v.components[i] > 0 then label = ('%s: %s'):format(component.label, TranslateCap('armory_item', ESX.Math.GroupDigits(v.components[i]))) else label = ('%s: %s'):format(component.label, TranslateCap('armory_free')) end end components[#components+1] = { icon = "fas fa-gun", title = 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, TranslateCap('armory_owned')) else if v.price > 0 then label = ('%s: %s'):format(weapon.label, TranslateCap('armory_item', ESX.Math.GroupDigits(v.price))) else label = ('%s: %s'):format(weapon.label, TranslateCap('armory_free')) end end elements[#elements+1] = { icon = "fas fa-gun", title = label, weaponLabel = weapon.label, name = weapon.name, components = components, price = v.price, hasWeapon = hasWeapon } end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} 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(TranslateCap('armory_bought', data.current.weaponLabel, ESX.Math.GroupDigits(data.current.price))) end ESX.CloseContext() OpenBuyWeaponsMenu() else ESX.ShowNotification(TranslateCap('armory_money')) end end, data.current.name, 1) end end) end function OpenWeaponComponentShop(components, weaponName, parentShop) ESX.OpenContext("right", components, function(menu,element) local data = {current = element} if data.current.hasComponent then ESX.ShowNotification(TranslateCap('armory_hascomponent')) else ESX.TriggerServerCallback('esx_policejob:buyWeapon', function(bought) if bought then if data.current.price > 0 then ESX.ShowNotification(TranslateCap('armory_bought', data.current.componentLabel, ESX.Math.GroupDigits(data.current.price))) end ESX.CloseContext() parentShop.close() OpenBuyWeaponsMenu() else ESX.ShowNotification(TranslateCap('armory_money')) end end, weaponName, 2, data.current.componentNum) end end) end function OpenGetStocksMenu() ESX.TriggerServerCallback('esx_policejob:getStockItems', function(items) local elements = { {unselectable = true, icon = "fas fa-box", title = TranslateCap('police_stock')} } for i=1, #items, 1 do elements[#elements+1] = { icon = "fas fa-box", title = 'x' .. items[i].count .. ' ' .. items[i].label, value = items[i].name } end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} local itemName = data.current.value local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, {title = TranslateCap('quantity'), input = true, inputType = "number", inputMin = 1, inputMax = 150, inputPlaceholder = TranslateCap('quantity_placeholder')}, {icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm"} } ESX.OpenContext("right", elements2, function(menu2,element2) local data2 = {value = menu2.eles[2].inputValue} local count = tonumber(data2.value) if not count then ESX.ShowNotification(TranslateCap('quantity_invalid')) else ESX.CloseContext() TriggerServerEvent('esx_policejob:getStockItem', itemName, count) Wait(300) OpenGetStocksMenu() end end) end) end) end function OpenPutStocksMenu() ESX.TriggerServerCallback('esx_policejob:getPlayerInventory', function(inventory) local elements = { {unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory')} } for i=1, #inventory.items, 1 do local item = inventory.items[i] if item.count > 0 then elements[#elements+1] = { icon = "fas fa-box", title = item.label .. ' x' .. item.count, type = 'item_standard', value = item.name } end end ESX.OpenContext("right", elements, function(menu,element) local data = {current = element} local itemName = data.current.value local elements2 = { {unselectable = true, icon = "fas fa-box", title = element.title}, {title = TranslateCap('quantity'), input = true, inputType = "number", inputMin = 1, inputMax = 150, inputPlaceholder = TranslateCap('quantity_placeholder')}, {icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm"} } ESX.OpenContext("right", elements2, function(menu2,element2) local data2 = {value = menu2.eles[2].inputValue} local count = tonumber(data2.value) if not count then ESX.ShowNotification(TranslateCap('quantity_invalid')) else ESX.CloseContext() TriggerServerEvent('esx_policejob:putStockItems', itemName, count) Wait(300) OpenPutStocksMenu() end end) end) end) end RegisterNetEvent('esx_phone:loaded') AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts) local specialContact = { name = TranslateCap('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 = TranslateCap('open_cloackroom') CurrentActionData = {} elseif part == 'Armory' then CurrentAction = 'menu_armory' CurrentActionMsg = TranslateCap('open_armory') CurrentActionData = {station = station} elseif part == 'Vehicles' then CurrentAction = 'menu_vehicle_spawner' CurrentActionMsg = TranslateCap('garage_prompt') CurrentActionData = {station = station, part = part, partNum = partNum} elseif part == 'Helicopters' then CurrentAction = 'Helicopters' CurrentActionMsg = TranslateCap('helicopter_prompt') CurrentActionData = {station = station, part = part, partNum = partNum} elseif part == 'BossActions' then CurrentAction = 'menu_boss_actions' CurrentActionMsg = TranslateCap('open_bossmenu') CurrentActionData = {} end end) AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum) if not isInShopMenu then ESX.CloseContext() 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 = TranslateCap('remove_prop') CurrentActionData = {entity = entity} end if GetEntityModel(entity) == `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 Wait(100) end TaskPlayAnim(playerPed, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0) RemoveAnimDict('mp_arresting') SetEnableHandcuffs(playerPed, true) DisablePlayerFiring(playerPed, true) SetCurrentPedWeapon(playerPed, `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) CreateThread(function() local wasDragged while true do local Sleep = 1500 if isHandcuffed and dragStatus.isDragged then Sleep = 50 local targetPed = GetPlayerPed(GetPlayerFromServerId(dragStatus.CopId)) if DoesEntityExist(targetPed) and IsPedOnFoot(targetPed) and not Player(dragStatus.CopId).state.isDead then if not wasDragged then AttachEntityToEntity(ESX.PlayerData.ped, targetPed, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) wasDragged = true else Wait(1000) end else wasDragged = false dragStatus.isDragged = false DetachEntity(ESX.PlayerData.ped, true, false) end elseif wasDragged then wasDragged = false DetachEntity(ESX.PlayerData.ped, true, false) end Wait(Sleep) end end) RegisterNetEvent('esx_policejob:putInVehicle') AddEventHandler('esx_policejob:putInVehicle', function() if isHandcuffed then local playerPed = PlayerPedId() local vehicle, distance = ESX.Game.GetClosestVehicle() if vehicle and distance < 5 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) RegisterNetEvent('esx_policejob:OutVehicle') AddEventHandler('esx_policejob:OutVehicle', function() local GetVehiclePedIsIn = GetVehiclePedIsIn local IsPedSittingInAnyVehicle = IsPedSittingInAnyVehicle local TaskLeaveVehicle = TaskLeaveVehicle if IsPedSittingInAnyVehicle(ESX.PlayerData.ped) then local vehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false) TaskLeaveVehicle(ESX.PlayerData.ped, vehicle, 64) end end) -- Handcuff CreateThread(function() local DisableControlAction = DisableControlAction local IsEntityPlayingAnim = IsEntityPlayingAnim while true do local Sleep = 1000 if isHandcuffed then Sleep = 0 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(ESX.PlayerData.ped, 'mp_arresting', 'idle', 3) ~= 1 then ESX.Streaming.RequestAnimDict('mp_arresting', function() TaskPlayAnim(ESX.PlayerData.ped, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0.0, false, false, false) RemoveAnimDict('mp_arresting') end) end end Wait(Sleep) end end) -- Create blips 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(TranslateCap('map_blip')) EndTextCommandSetBlipName(blip) end end) -- Draw markers and more CreateThread(function() while true do local Sleep = 1500 if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then Sleep = 500 local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local isInMarker, hasExited = false, false 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) Sleep = 0 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) Sleep = 0 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) Sleep = 0 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) Sleep = 0 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) Sleep = 0 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 end Wait(Sleep) end end) -- Enter / Exit entity zone events 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 local Sleep = 1500 local GetEntityCoords = GetEntityCoords local GetClosestObjectOfType = GetClosestObjectOfType local DoesEntityExist = DoesEntityExist local playerCoords = GetEntityCoords(ESX.PlayerData.ped) local closestDistance = -1 local closestEntity = nil for i=1, #trackedEntities, 1 do local object = GetClosestObjectOfType(playerCoords, 3.0, trackedEntities[i], false, false, false) if DoesEntityExist(object) then Sleep = 500 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 Wait(Sleep) end end) ESX.RegisterInput("police:interact", "(ESX PoliceJob) " .. TranslateCap('interaction'), "keyboard", "E", function() if not CurrentAction then return end if not ESX.PlayerData.job or (ESX.PlayerData.job and not ESX.PlayerData.job.name == 'police') then return end 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(TranslateCap('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(TranslateCap('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(TranslateCap('service_not')) end elseif CurrentAction == 'delete_vehicle' then ESX.Game.DeleteVehicle(CurrentActionData.vehicle) elseif CurrentAction == 'menu_boss_actions' then ESX.CloseContext() TriggerEvent('esx_society:openBossMenu', 'police', function(data, menu) ESX.CloseContext() CurrentAction = 'menu_boss_actions' CurrentActionMsg = TranslateCap('open_bossmenu') CurrentActionData = {} end, { wash = false }) -- disable washing money elseif CurrentAction == 'remove_entity' then DeleteEntity(CurrentActionData.entity) end CurrentAction = nil end) ESX.RegisterInput("police:quickactions", "(ESX PoliceJob) "..TranslateCap('quick_actions'), "keyboard", "F6", function() if not ESX.PlayerData.job or (ESX.PlayerData.job.name ~= 'police') or isDead then return end if not Config.EnableESXService then OpenPoliceActionsMenu() elseif playerInService then OpenPoliceActionsMenu() else ESX.ShowNotification(TranslateCap('service_not')) end end) CreateThread(function() while true do local Sleep = 1000 if CurrentAction then Sleep = 0 ESX.ShowHelpNotification(CurrentActionMsg) end Wait(Sleep) 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 AddEventHandler('esx:onPlayerSpawn', 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(TranslateCap('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(TranslateCap('impound_successful')) currentTask.busy = false end