local Keys = { ["ESC"] = 322, ["F1"] = 288, ["F2"] = 289, ["F3"] = 170, ["F5"] = 166, ["F6"] = 167, ["F7"] = 168, ["F8"] = 169, ["F9"] = 56, ["F10"] = 57, ["~"] = 243, ["1"] = 157, ["2"] = 158, ["3"] = 160, ["4"] = 164, ["5"] = 165, ["6"] = 159, ["7"] = 161, ["8"] = 162, ["9"] = 163, ["-"] = 84, ["="] = 83, ["BACKSPACE"] = 177, ["TAB"] = 37, ["Q"] = 44, ["W"] = 32, ["E"] = 38, ["R"] = 45, ["T"] = 245, ["Y"] = 246, ["U"] = 303, ["P"] = 199, ["["] = 39, ["]"] = 40, ["ENTER"] = 18, ["CAPS"] = 137, ["A"] = 34, ["S"] = 8, ["D"] = 9, ["F"] = 23, ["G"] = 47, ["H"] = 74, ["K"] = 311, ["L"] = 182, ["LEFTSHIFT"] = 21, ["Z"] = 20, ["X"] = 73, ["C"] = 26, ["V"] = 0, ["B"] = 29, ["N"] = 249, ["M"] = 244, [","] = 82, ["."] = 81, ["LEFTCTRL"] = 36, ["LEFTALT"] = 19, ["SPACE"] = 22, ["RIGHTCTRL"] = 70, ["HOME"] = 213, ["PAGEUP"] = 10, ["PAGEDOWN"] = 11, ["DELETE"] = 178, ["LEFT"] = 174, ["RIGHT"] = 175, ["TOP"] = 27, ["DOWN"] = 173, ["NENTER"] = 201, ["N4"] = 108, ["N5"] = 60, ["N6"] = 107, ["N+"] = 96, ["N-"] = 97, ["N7"] = 117, ["N8"] = 61, ["N9"] = 118 } local PlayerData = {} local HasAlreadyEnteredMarker = false local LastStation = nil local LastPart = nil local LastPartNum = nil local LastEntity = nil local CurrentAction = nil local CurrentActionMsg = '' local CurrentActionData = {} local IsHandcuffed = false local HandcuffTimer = {} local DragStatus = {} DragStatus.IsDragged = false local hasAlreadyJoined = false local blipsCops = {} local isDead = false local CurrentTask = {} ESX = nil Citizen.CreateThread(function() while ESX == nil do TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) Citizen.Wait(0) end Citizen.Wait(5000) PlayerData = ESX.GetPlayerData() end) function SetVehicleMaxMods(vehicle) local props = { modEngine = 2, modBrakes = 2, modTransmission = 2, modSuspension = 3, modTurbo = true, } ESX.Game.SetVehicleProperties(vehicle, props) end function cleanPlayer(playerPed) SetPedArmour(playerPed, 0) ClearPedBloodDamage(playerPed) ResetPedVisibleDamage(playerPed) ClearPedLastWeaponDamage(playerPed) ResetPedMovementClipset(playerPed, 0) end function setUniform(job, playerPed) TriggerEvent('skinchanger:getSkin', function(skin) if skin.sex == 0 then if Config.Uniforms[job].male ~= nil then TriggerEvent('skinchanger:loadClothes', skin, Config.Uniforms[job].male) else ESX.ShowNotification(_U('no_outfit')) end if job == 'bullet_wear' then SetPedArmour(playerPed, 100) end else if Config.Uniforms[job].female ~= nil then TriggerEvent('skinchanger:loadClothes', skin, Config.Uniforms[job].female) else ESX.ShowNotification(_U('no_outfit')) end if job == 'bullet_wear' then SetPedArmour(playerPed, 100) end end end) end function OpenCloakroomMenu() local playerPed = PlayerPedId() local elements = { { label = _U('citizen_wear'), value = 'citizen_wear' }, { label = _U('bullet_wear'), value = 'bullet_wear' }, { label = _U('gilet_wear'), value = 'gilet_wear' } } if PlayerData.job.grade_name == 'recruit' then table.insert(elements, {label = _U('police_wear'), value = 'cadet_wear'}) end if PlayerData.job.grade_name == 'officer' then table.insert(elements, {label = _U('police_wear'), value = 'police_wear'}) end if PlayerData.job.grade_name == 'sergeant' then table.insert(elements, {label = _U('police_wear'), value = 'sergeant_wear'}) end if PlayerData.job.grade_name == 'lieutenant' then table.insert(elements, {label = _U('police_wear'), value = 'lieutenant_wear'}) end if PlayerData.job.grade_name == 'boss' then table.insert(elements, {label = _U('police_wear'), value = 'commandant_wear'}) end if Config.EnableNonFreemodePeds then table.insert(elements, {label = _U('sheriff_wear'), value = 'sheriff_wear_freemode', maleModel = 's_m_y_sheriff_01', femaleModel = 's_f_y_sheriff_01'}) table.insert(elements, {label = _U('lieutenant_wear'), value = 'lieutenant_wear_freemode', maleModel = 's_m_y_swat_01', femaleModel = 's_m_y_swat_01'}) table.insert(elements, {label = _U('commandant_wear'), value = 'commandant_wear_freemode', maleModel = 's_m_y_swat_01', femaleModel = 's_m_y_swat_01'}) 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 ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) TriggerEvent('skinchanger:loadSkin', skin) end) end if data.current.value == 'cadet_wear' or data.current.value == 'police_wear' or data.current.value == 'sergeant_wear' or data.current.value == 'lieutenant_wear' or data.current.value == 'commandant_wear' or data.current.value == 'bullet_wear' or data.current.value == 'gilet_wear' then setUniform(data.current.value, playerPed) end if data.current.value == 'sheriff_wear_freemode' or data.current.value == 'lieutenant_wear_freemode' or data.current.value == 'commandant_wear_freemode' then local model = nil ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) if skin.sex == 0 then model = GetHashKey(data.current.maleModel) else model = GetHashKey(data.current.femaleModel) end end) RequestModel(model) while not HasModelLoaded(model) do RequestModel(model) Citizen.Wait(1) end SetPlayerModel(PlayerId(), model) SetModelAsNoLongerNeeded(model) end CurrentAction = 'menu_cloakroom' CurrentActionMsg = _U('open_cloackroom') CurrentActionData = {} end, function(data, menu) menu.close() CurrentAction = 'menu_cloakroom' CurrentActionMsg = _U('open_cloackroom') CurrentActionData = {} end ) end function OpenArmoryMenu(station) if Config.EnableArmoryManagement then local elements = { {label = _U('get_weapon'), value = 'get_weapon'}, {label = _U('put_weapon'), value = 'put_weapon'}, {label = _U('remove_object'), value = 'get_stock'}, {label = _U('deposit_object'), value = 'put_stock'} } if PlayerData.job.grade_name == 'boss' then table.insert(elements, {label = _U('buy_weapons'), value = 'buy_weapons'}) 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() end if data.current.value == 'put_weapon' then OpenPutWeaponMenu() end if data.current.value == 'buy_weapons' then OpenBuyWeaponsMenu(station) end if data.current.value == 'put_stock' then OpenPutStocksMenu() end if 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 ) else local elements = {} for i=1, #Config.PoliceStations[station].AuthorizedWeapons, 1 do local weapon = Config.PoliceStations[station].AuthorizedWeapons[i] table.insert(elements, {label = ESX.GetWeaponLabel(weapon.name), value = weapon.name}) end ESX.UI.Menu.CloseAll() ESX.UI.Menu.Open( 'default', GetCurrentResourceName(), 'armory', { title = _U('armory'), align = 'top-left', elements = elements, }, function(data, menu) local weapon = data.current.value TriggerServerEvent('esx_policejob:giveWeapon', weapon, 1000) end, function(data, menu) menu.close() CurrentAction = 'menu_armory' CurrentActionMsg = _U('open_armory') CurrentActionData = {station = station} end ) end end function OpenVehicleSpawnerMenu(station, partNum) local vehicles = Config.PoliceStations[station].Vehicles ESX.UI.Menu.CloseAll() if Config.EnableSocietyOwnedVehicles then local elements = {} ESX.TriggerServerCallback('esx_society:getVehiclesInGarage', function(garageVehicles) for i=1, #garageVehicles, 1 do table.insert(elements, {label = GetDisplayNameFromVehicleModel(garageVehicles[i].model) .. ' [' .. garageVehicles[i].plate .. ']', value = garageVehicles[i]}) end ESX.UI.Menu.Open( 'default', GetCurrentResourceName(), 'vehicle_spawner', { title = _U('vehicle_menu'), align = 'top-left', elements = elements, }, function(data, menu) menu.close() local vehicleProps = data.current.value ESX.Game.SpawnVehicle(vehicleProps.model, vehicles[partNum].SpawnPoint, 270.0, function(vehicle) ESX.Game.SetVehicleProperties(vehicle, vehicleProps) local playerPed = PlayerPedId() TaskWarpPedIntoVehicle(playerPed, vehicle, -1) end) TriggerServerEvent('esx_society:removeVehicleFromGarage', 'police', vehicleProps) end, function(data, menu) menu.close() CurrentAction = 'menu_vehicle_spawner' CurrentActionMsg = _U('vehicle_spawner') CurrentActionData = {station = station, partNum = partNum} end ) end, 'police') else local elements = {} local sharedVehicles = Config.AuthorizedVehicles.Shared for i=1, #sharedVehicles, 1 do table.insert(elements, { label = sharedVehicles[i].label, model = sharedVehicles[i].model}) end local authorizedVehicles = Config.AuthorizedVehicles[PlayerData.job.grade_name] for i=1, #authorizedVehicles, 1 do table.insert(elements, { label = authorizedVehicles[i].label, model = authorizedVehicles[i].model}) end ESX.UI.Menu.Open( 'default', GetCurrentResourceName(), 'vehicle_spawner', { title = _U('vehicle_menu'), align = 'top-left', elements = elements, }, function(data, menu) menu.close() local model = data.current.model local vehicle = GetClosestVehicle(vehicles[partNum].SpawnPoint.x, vehicles[partNum].SpawnPoint.y, vehicles[partNum].SpawnPoint.z, 3.0, 0, 71) if not DoesEntityExist(vehicle) then local playerPed = PlayerPedId() if Config.MaxInService == -1 then ESX.Game.SpawnVehicle(model, { x = vehicles[partNum].SpawnPoint.x, y = vehicles[partNum].SpawnPoint.y, z = vehicles[partNum].SpawnPoint.z }, vehicles[partNum].Heading, function(vehicle) TaskWarpPedIntoVehicle(playerPed, vehicle, -1) SetVehicleMaxMods(vehicle) end) else ESX.TriggerServerCallback('esx_service:enableService', function(canTakeService, maxInService, inServiceCount) if canTakeService then ESX.Game.SpawnVehicle(model, { x = vehicles[partNum].SpawnPoint.x, y = vehicles[partNum].SpawnPoint.y, z = vehicles[partNum].SpawnPoint.z }, vehicles[partNum].Heading, function(vehicle) TaskWarpPedIntoVehicle(playerPed, vehicle, -1) SetVehicleMaxMods(vehicle) end) else ESX.ShowNotification(_U('service_max', inServiceCount, maxInService)) end end, 'police') end else ESX.ShowNotification(_U('vehicle_out')) end end, function(data, menu) menu.close() CurrentAction = 'menu_vehicle_spawner' CurrentActionMsg = _U('vehicle_spawner') CurrentActionData = {station = station, partNum = partNum} end ) 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 = 'body_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 == 'body_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 coords = GetEntityCoords(playerPed) 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) coords = GetEntityCoords(playerPed) vehicle = ESX.Game.GetVehicleInDirection() action = data2.current.value if action == 'search_database' then LookupVehicle() elseif DoesEntityExist(vehicle) then local vehicleData = ESX.Game.GetVehicleProperties(vehicle) if action == 'vehicle_infos' then 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 SetTextComponentFormat('STRING') AddTextComponentString(_U('impound_prompt')) DisplayHelpTextFromStringLabel(0, 0, 1, -1) 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'), value = 'prop_roadcone02a'}, {label = _U('barrier'), value = 'prop_barrier_work06a'}, {label = _U('spikestrips'), value = 'p_ld_stinger_s'}, {label = _U('box'), value = 'prop_boxpile_07d'}, {label = _U('cash'), value = 'hei_prop_cash_crate_half_full'} } }, function(data2, menu2) local model = data2.current.value local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local forward = GetEntityForwardVector(playerPed) local x, y, z = table.unpack(coords + forward * 1.0) if model == 'prop_roadcone02a' then z = z - 2.0 end ESX.Game.SpawnObject(model, { x = x, y = y, z = z }, 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 = {} local nameLabel = _U('name', data.name) local jobLabel = nil local sexLabel = nil local dobLabel = nil local heightLabel = nil local idLabel = nil if data.job.grade_label ~= nil and data.job.grade_label ~= '' then jobLabel = _U('job', data.job.label .. ' - ' .. data.job.grade_label) else jobLabel = _U('job', data.job.label) end if Config.EnableESXIdentity then nameLabel = _U('name', data.firstname .. ' ' .. data.lastname) if data.sex ~= nil then if string.lower(data.sex) == 'm' then sexLabel = _U('sex', _U('male')) else sexLabel = _U('sex', _U('female')) end else sexLabel = _U('sex', _U('unknown')) end if data.dob ~= nil then dobLabel = _U('dob', data.dob) else dobLabel = _U('dob', _U('unknown')) end if data.height ~= nil then heightLabel = _U('height', data.height) else heightLabel = _U('height', _U('unknown')) end if data.name ~= nil then idLabel = _U('id', data.name) else idLabel = _U('id', _U('unknown')) end end local elements = { {label = nameLabel, value = nil}, {label = jobLabel, value = nil}, } if Config.EnableESXIdentity then table.insert(elements, {label = sexLabel, value = nil}) table.insert(elements, {label = dobLabel, value = nil}) table.insert(elements, {label = heightLabel, value = nil}) table.insert(elements, {label = idLabel, value = nil}) end if data.drunk ~= nil then table.insert(elements, {label = _U('bac', data.drunk), value = nil}) end if data.licenses ~= nil then table.insert(elements, {label = _U('license_label'), value = nil}) for i=1, #data.licenses, 1 do table.insert(elements, {label = data.licenses[i].label, value = nil}) end end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction', { title = _U('citizen_interaction'), align = 'top-left', elements = elements, }, function(data, menu) end, 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.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'), value = nil}) 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'), value = nil}) 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) local itemType = data.current.itemType local itemName = data.current.value local amount = data.current.amount if data.current.value ~= nil then TriggerServerEvent('esx_policejob:confiscatePlayerItem', GetPlayerServerId(player), itemType, itemName, 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 i=1, #fines, 1 do table.insert(elements, { label = fines[i].label .. ' $' .. fines[i].amount .. '', value = fines[i].id, amount = fines[i].amount, fineLabel = fines[i].label }) end ESX.UI.Menu.Open( 'default', GetCurrentResourceName(), 'fine_category', { title = _U('fine'), align = 'top-left', elements = elements, }, function(data, menu) local label = data.current.fineLabel local amount = data.current.amount menu.close() if Config.EnablePlayerManagement then TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_police', _U('fine_total', label), amount) else TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), '', _U('fine_total', label), 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 data.value == nil or length < 8 or length > 13 then ESX.ShowNotification(_U('search_database_error_invalid')) else ESX.TriggerServerCallback('esx_policejob:getVehicleFromPlate', function(owner, found) if found then ESX.ShowNotification(_U('search_database_found', owner)) else ESX.ShowNotification(_U('search_database_error_not_found')) end end, data.value) menu.close() end end, function(data, menu) menu.close() end) end function ShowPlayerLicense(player) local elements = {} local targetName ESX.TriggerServerCallback('esx_policejob:getOtherPlayerData', function(data) if data.licenses ~= nil then for i=1, #data.licenses, 1 do if data.licenses[i].label ~= nil and data.licenses[i].type ~= nil then table.insert(elements, {label = data.licenses[i].label, value = data.licenses[i].type}) end end end if Config.EnableESXIdentity then targetName = data.firstname .. ' ' .. data.lastname else targetName = data.name 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, targetName)) TriggerServerEvent('esx_policejob:message', GetPlayerServerId(player), _U('license_revoked', data.current.label)) TriggerServerEvent('esx_license:removeLicense', GetPlayerServerId(player), data.current.value) 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 i=1, #bills, 1 do table.insert(elements, {label = bills[i].label .. ' - $' .. bills[i].amount .. '', value = bills[i].id}) end ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'billing', { title = _U('unpaid_bills'), align = 'top-left', elements = elements }, function(data, menu) end, function(data, menu) menu.close() end) end, GetPlayerServerId(player)) end function OpenVehicleInfosMenu(vehicleData) ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(infos) local elements = {} table.insert(elements, {label = _U('plate', infos.plate), value = nil}) if infos.owner == nil then table.insert(elements, {label = _U('owner_unknown'), value = nil}) else table.insert(elements, {label = _U('owner', infos.owner), value = nil}) 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 --local ammo = GetAmmoInPedWeapon(playerPed, weaponHash) 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(station) ESX.TriggerServerCallback('esx_policejob:getArmoryWeapons', function(weapons) local elements = {} for i=1, #Config.PoliceStations[station].AuthorizedWeapons, 1 do local weapon = Config.PoliceStations[station].AuthorizedWeapons[i] local count = 0 for i=1, #weapons, 1 do if weapons[i].name == weapon.name then count = weapons[i].count break end end table.insert(elements, {label = 'x' .. count .. ' ' .. ESX.GetWeaponLabel(weapon.name) .. ' $' .. weapon.price, value = weapon.name, price = weapon.price}) end ESX.UI.Menu.Open( 'default', GetCurrentResourceName(), 'armory_buy_weapons', { title = _U('buy_weapon_menu'), align = 'top-left', elements = elements, }, function(data, menu) ESX.TriggerServerCallback('esx_policejob:buy', function(hasEnoughMoney) if hasEnoughMoney then ESX.TriggerServerCallback('esx_policejob:addArmoryWeapon', function() OpenBuyWeaponsMenu(station) end, data.current.value, false) else ESX.ShowNotification(_U('not_enough_money')) end end, data.current.price) end, function(data, menu) menu.close() end ) 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 count == nil then ESX.ShowNotification(_U('quantity_invalid')) else menu2.close() menu.close() OpenGetStocksMenu() TriggerServerEvent('esx_policejob:getStockItem', itemName, count) 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 count == nil then ESX.ShowNotification(_U('quantity_invalid')) else menu2.close() menu.close() OpenPutStocksMenu() TriggerServerEvent('esx_policejob:putStockItems', itemName, count) 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) 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) AddEventHandler('esx_policejob:hasEnteredMarker', function(station, part, partNum) if part == 'Cloakroom' then CurrentAction = 'menu_cloakroom' CurrentActionMsg = _U('open_cloackroom') CurrentActionData = {} end if part == 'Armory' then CurrentAction = 'menu_armory' CurrentActionMsg = _U('open_armory') CurrentActionData = {station = station} end if part == 'VehicleSpawner' then CurrentAction = 'menu_vehicle_spawner' CurrentActionMsg = _U('vehicle_spawner') CurrentActionData = {station = station, partNum = partNum} end if part == 'HelicopterSpawner' then local helicopters = Config.PoliceStations[station].Helicopters if not IsAnyVehicleNearPoint(helicopters[partNum].SpawnPoint.x, helicopters[partNum].SpawnPoint.y, helicopters[partNum].SpawnPoint.z, 3.0) then ESX.Game.SpawnVehicle('polmav', { x = helicopters[partNum].SpawnPoint.x, y = helicopters[partNum].SpawnPoint.y, z = helicopters[partNum].SpawnPoint.z }, helicopters[partNum].Heading, function(vehicle) SetVehicleModKit(vehicle, 0) SetVehicleLivery(vehicle, 0) end) end end if part == 'VehicleDeleter' then local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) if IsPedInAnyVehicle(playerPed, false) then local vehicle = GetVehiclePedIsIn(playerPed, false) if DoesEntityExist(vehicle) then CurrentAction = 'delete_vehicle' CurrentActionMsg = _U('store_vehicle') CurrentActionData = {vehicle = vehicle} end end end if part == 'BossActions' then CurrentAction = 'menu_boss_actions' CurrentActionMsg = _U('open_bossmenu') CurrentActionData = {} end end) AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum) ESX.UI.Menu.CloseAll() CurrentAction = nil end) AddEventHandler('esx_policejob:hasEnteredEntityZone', function(entity) local playerPed = PlayerPedId() if PlayerData.job ~= nil and PlayerData.job.name == 'police' and not IsPedInAnyVehicle(playerPed, false) 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() Citizen.CreateThread(function() 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) 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 not IsHandcuffed then return end DragStatus.IsDragged = not DragStatus.IsDragged DragStatus.CopId = tonumber(copID) end) Citizen.CreateThread(function() local playerPed local targetPed while true do Citizen.Wait(1) if IsHandcuffed then playerPed = PlayerPedId() if DragStatus.IsDragged then targetPed = GetPlayerPed(GetPlayerFromServerId(DragStatus.CopId)) -- undrag if target is in an vehicle if not IsPedSittingInAnyVehicle(targetPed) then AttachEntityToEntity(playerPed, targetPed, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) else DragStatus.IsDragged = false DetachEntity(playerPed, true, false) end else DetachEntity(playerPed, true, false) end else Citizen.Wait(500) end end end) RegisterNetEvent('esx_policejob:putInVehicle') AddEventHandler('esx_policejob:putInVehicle', function() local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) if not IsHandcuffed then return end if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then local vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 5.0, 0, 71) if DoesEntityExist(vehicle) then local maxSeats = GetVehicleMaxNumberOfPassengers(vehicle) local freeSeat = nil for i=maxSeats - 1, 0, -1 do if IsVehicleSeatFree(vehicle, i) then freeSeat = i break end end if freeSeat ~= nil then TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat) DragStatus.IsDragged = false end end end end) RegisterNetEvent('esx_policejob:OutVehicle') AddEventHandler('esx_policejob:OutVehicle', function() local playerPed = PlayerPedId() if not IsPedSittingInAnyVehicle(playerPed) then return end local vehicle = GetVehiclePedIsIn(playerPed, false) TaskLeaveVehicle(playerPed, vehicle, 16) end) -- Handcuff Citizen.CreateThread(function() while true do Citizen.Wait(1) if IsHandcuffed then DisableControlAction(2, 1, true) -- Disable pan DisableControlAction(2, 2, true) -- Disable tilt DisableControlAction(2, 24, true) -- Attack DisableControlAction(2, 257, true) -- Attack 2 DisableControlAction(2, 25, true) -- Aim DisableControlAction(2, 263, true) -- Melee Attack 1 DisableControlAction(2, Keys['R'], true) -- Reload DisableControlAction(2, Keys['TOP'], true) -- Open phone (not needed?) DisableControlAction(2, Keys['SPACE'], true) -- Jump DisableControlAction(2, Keys['Q'], true) -- Cover DisableControlAction(2, Keys['TAB'], true) -- Select Weapon DisableControlAction(2, Keys['F'], true) -- Also 'enter'? DisableControlAction(2, Keys['F1'], true) -- Disable phone DisableControlAction(2, Keys['F2'], true) -- Inventory DisableControlAction(2, Keys['F3'], true) -- Animations DisableControlAction(2, Keys['V'], true) -- Disable changing view DisableControlAction(2, Keys['P'], true) -- Disable pause screen DisableControlAction(2, 59, true) -- Disable steering in vehicle DisableControlAction(2, Keys['LEFTCTRL'], 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 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.Pos.x, v.Blip.Pos.y, v.Blip.Pos.z) 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") AddTextComponentString(_U('map_blip')) EndTextCommandSetBlipName(blip) end end) -- Display markers Citizen.CreateThread(function() while true do Wait(0) if PlayerData.job ~= nil and PlayerData.job.name == 'police' then local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) for k,v in pairs(Config.PoliceStations) do for i=1, #v.Cloakrooms, 1 do if GetDistanceBetweenCoords(coords, v.Cloakrooms[i].x, v.Cloakrooms[i].y, v.Cloakrooms[i].z, true) < Config.DrawDistance then DrawMarker(Config.MarkerType, v.Cloakrooms[i].x, v.Cloakrooms[i].y, v.Cloakrooms[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false) end end for i=1, #v.Armories, 1 do if GetDistanceBetweenCoords(coords, v.Armories[i].x, v.Armories[i].y, v.Armories[i].z, true) < Config.DrawDistance then DrawMarker(Config.MarkerType, v.Armories[i].x, v.Armories[i].y, v.Armories[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false) end end for i=1, #v.Vehicles, 1 do if GetDistanceBetweenCoords(coords, v.Vehicles[i].Spawner.x, v.Vehicles[i].Spawner.y, v.Vehicles[i].Spawner.z, true) < Config.DrawDistance then DrawMarker(Config.MarkerType, v.Vehicles[i].Spawner.x, v.Vehicles[i].Spawner.y, v.Vehicles[i].Spawner.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false) end end for i=1, #v.VehicleDeleters, 1 do if GetDistanceBetweenCoords(coords, v.VehicleDeleters[i].x, v.VehicleDeleters[i].y, v.VehicleDeleters[i].z, true) < Config.DrawDistance then DrawMarker(Config.MarkerType, v.VehicleDeleters[i].x, v.VehicleDeleters[i].y, v.VehicleDeleters[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false) end end if Config.EnablePlayerManagement and PlayerData.job ~= nil and PlayerData.job.name == 'police' and PlayerData.job.grade_name == 'boss' then for i=1, #v.BossActions, 1 do if not v.BossActions[i].disabled and GetDistanceBetweenCoords(coords, v.BossActions[i].x, v.BossActions[i].y, v.BossActions[i].z, true) < Config.DrawDistance then DrawMarker(Config.MarkerType, v.BossActions[i].x, v.BossActions[i].y, v.BossActions[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false) end end end end end end end) -- Enter / Exit marker events Citizen.CreateThread(function() while true do Wait(0) if PlayerData.job ~= nil and PlayerData.job.name == 'police' then local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local isInMarker = false local currentStation = nil local currentPart = nil local currentPartNum = nil for k,v in pairs(Config.PoliceStations) do for i=1, #v.Cloakrooms, 1 do if GetDistanceBetweenCoords(coords, v.Cloakrooms[i].x, v.Cloakrooms[i].y, v.Cloakrooms[i].z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'Cloakroom' currentPartNum = i end end for i=1, #v.Armories, 1 do if GetDistanceBetweenCoords(coords, v.Armories[i].x, v.Armories[i].y, v.Armories[i].z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'Armory' currentPartNum = i end end for i=1, #v.Vehicles, 1 do if GetDistanceBetweenCoords(coords, v.Vehicles[i].Spawner.x, v.Vehicles[i].Spawner.y, v.Vehicles[i].Spawner.z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'VehicleSpawner' currentPartNum = i end if GetDistanceBetweenCoords(coords, v.Vehicles[i].SpawnPoint.x, v.Vehicles[i].SpawnPoint.y, v.Vehicles[i].SpawnPoint.z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'VehicleSpawnPoint' currentPartNum = i end end for i=1, #v.Helicopters, 1 do if GetDistanceBetweenCoords(coords, v.Helicopters[i].Spawner.x, v.Helicopters[i].Spawner.y, v.Helicopters[i].Spawner.z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'HelicopterSpawner' currentPartNum = i end if GetDistanceBetweenCoords(coords, v.Helicopters[i].SpawnPoint.x, v.Helicopters[i].SpawnPoint.y, v.Helicopters[i].SpawnPoint.z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'HelicopterSpawnPoint' currentPartNum = i end end for i=1, #v.VehicleDeleters, 1 do if GetDistanceBetweenCoords(coords, v.VehicleDeleters[i].x, v.VehicleDeleters[i].y, v.VehicleDeleters[i].z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'VehicleDeleter' currentPartNum = i end end if Config.EnablePlayerManagement and PlayerData.job ~= nil and PlayerData.job.name == 'police' and PlayerData.job.grade_name == 'boss' then for i=1, #v.BossActions, 1 do if GetDistanceBetweenCoords(coords, v.BossActions[i].x, v.BossActions[i].y, v.BossActions[i].z, true) < Config.MarkerSize.x then isInMarker = true currentStation = k currentPart = 'BossActions' currentPartNum = i end end end end local hasExited = false if isInMarker and not HasAlreadyEnteredMarker or (isInMarker and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum) ) then if (LastStation ~= nil and LastPart ~= nil and LastPartNum ~= nil) 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 end end) -- Enter / Exit entity zone events Citizen.CreateThread(function() local trackedEntities = { 'prop_roadcone02a', 'prop_barrier_work06a', 'p_ld_stinger_s', 'prop_boxpile_07d', 'hei_prop_cash_crate_half_full' } while true do Citizen.Wait(0) local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local closestDistance = -1 local closestEntity = nil for i=1, #trackedEntities, 1 do local object = GetClosestObjectOfType(coords.x, coords.y, coords.z, 3.0, GetHashKey(trackedEntities[i]), false, false, false) if DoesEntityExist(object) then local objCoords = GetEntityCoords(object) local distance = GetDistanceBetweenCoords(coords.x, coords.y, coords.z, objCoords.x, objCoords.y, objCoords.z, true) 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 ~= nil 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 ~= nil then SetTextComponentFormat('STRING') AddTextComponentString(CurrentActionMsg) DisplayHelpTextFromStringLabel(0, 0, 1, -1) if IsControlJustReleased(0, Keys['E']) and PlayerData.job ~= nil and PlayerData.job.name == 'police' then if CurrentAction == 'menu_cloakroom' then OpenCloakroomMenu() elseif CurrentAction == 'menu_armory' then OpenArmoryMenu(CurrentActionData.station) elseif CurrentAction == 'menu_vehicle_spawner' then OpenVehicleSpawnerMenu(CurrentActionData.station, CurrentActionData.partNum) elseif CurrentAction == 'delete_vehicle' then if Config.EnableSocietyOwnedVehicles then local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) TriggerServerEvent('esx_society:putVehicleInGarage', 'police', vehicleProps) else if GetEntityModel(vehicle) == GetHashKey('police') or GetEntityModel(vehicle) == GetHashKey('police2') or GetEntityModel(vehicle) == GetHashKey('police3') or GetEntityModel(vehicle) == GetHashKey('police4') or GetEntityModel(vehicle) == GetHashKey('policeb') or GetEntityModel(vehicle) == GetHashKey('policet') then TriggerServerEvent('esx_service:disableService', 'police') end end 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, Keys['F6']) and not isDead and PlayerData.job ~= nil and PlayerData.job.name == 'police' and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions') then OpenPoliceActionsMenu() end if IsControlJustReleased(0, Keys['E']) 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) ped = GetPlayerPed(id) 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(veh))) -- 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 = {} -- Is the player a cop? In that case show all the blips for other cops if PlayerData.job ~= nil and 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 for id = 0, 32 do if NetworkIsPlayerActive(id) and GetPlayerPed(id) ~= PlayerPedId() and GetPlayerName(id) == players[i].name then createBlip(id) end 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') 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