mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-31 18:28:52 +00:00
312 lines
12 KiB
Lua
312 lines
12 KiB
Lua
local self = ESX.Modules['job_police']
|
|
|
|
-- Locals
|
|
local Input = ESX.Modules['input']
|
|
|
|
RegisterNetEvent('esx:setJob')
|
|
AddEventHandler('esx:setJob', function(job)
|
|
Citizen.Wait(5000)
|
|
TriggerServerEvent('esx_policejob:forceBlip')
|
|
end)
|
|
|
|
RegisterNetEvent('esx_phone:loaded')
|
|
AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts)
|
|
|
|
local specialContact = {
|
|
name = _U('job_police: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 self.Config.EnableESXService and not playerInService then
|
|
CancelEvent()
|
|
end
|
|
end
|
|
|
|
end)
|
|
|
|
AddEventHandler('esx_policejob:hasEnteredMarker', function(station, part, partNum)
|
|
if part == 'Cloakroom' then
|
|
self.CurrentAction = 'menu_cloakroom'
|
|
self.CurrentActionMsg = _U('job_police:open_cloackroom')
|
|
self.CurrentActionData = {}
|
|
elseif part == 'Armory' then
|
|
self.CurrentAction = 'menu_armory'
|
|
self.CurrentActionMsg = _U('job_police:open_armory')
|
|
self.CurrentActionData = {station = station}
|
|
elseif part == 'Vehicles' then
|
|
self.CurrentAction = 'menu_vehicle_spawner'
|
|
self.CurrentActionMsg = _U('job_police:garage_prompt')
|
|
self.CurrentActionData = {station = station, part = part, partNum = partNum}
|
|
elseif part == 'Helicopters' then
|
|
self.CurrentAction = 'Helicopters'
|
|
self.CurrentActionMsg = _U('job_police:helicopter_prompt')
|
|
self.CurrentActionData = {station = station, part = part, partNum = partNum}
|
|
elseif part == 'BossActions' then
|
|
self.CurrentAction = 'menu_boss_actions'
|
|
self.CurrentActionMsg = _U('job_police:open_bossmenu')
|
|
self.CurrentActionData = {}
|
|
end
|
|
end)
|
|
|
|
AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum)
|
|
if not isInShopMenu then
|
|
ESX.UI.Menu.CloseAll()
|
|
end
|
|
|
|
self.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
|
|
self.CurrentAction = 'remove_entity'
|
|
self.CurrentActionMsg = _U('job_police:remove_prop')
|
|
self.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 self.CurrentAction == 'remove_entity' then
|
|
self.CurrentAction = nil
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx_policejob:handcuff')
|
|
AddEventHandler('esx_policejob:handcuff', function()
|
|
self.IsHandcuffed = not self.IsHandcuffed
|
|
local playerPed = PlayerPedId()
|
|
|
|
if self.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 self.Config.EnableHandcuffTimer then
|
|
if handcuffTimer.active then
|
|
ESX.ClearTimeout(handcuffTimer.task)
|
|
end
|
|
|
|
StartHandcuffTimer()
|
|
end
|
|
else
|
|
if self.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 self.IsHandcuffed then
|
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
self.IsHandcuffed = false
|
|
|
|
ClearPedSecondaryTask(playerPed)
|
|
SetEnableHandcuffs(playerPed, false)
|
|
DisablePlayerFiring(playerPed, false)
|
|
SetPedCanPlayGestureAnims(playerPed, true)
|
|
FreezeEntityPosition(playerPed, false)
|
|
DisplayRadar(true)
|
|
|
|
-- end timer
|
|
if self.Config.EnableHandcuffTimer and handcuffTimer.active then
|
|
ESX.ClearTimeout(handcuffTimer.task)
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx_policejob:drag')
|
|
AddEventHandler('esx_policejob:drag', function(copId)
|
|
if self.IsHandcuffed then
|
|
dragStatus.isDragged = not dragStatus.isDragged
|
|
dragStatus.CopId = copId
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx_policejob:putInVehicle')
|
|
AddEventHandler('esx_policejob:putInVehicle', function()
|
|
if self.IsHandcuffed then
|
|
local playerPed = PlayerPedId()
|
|
local coords = GetEntityCoords(playerPed)
|
|
|
|
if IsAnyVehicleNearPoint(coords, 5.0) then
|
|
local vehicle = GetClosestVehicle(coords, 5.0, 0, 71)
|
|
|
|
if DoesEntityExist(vehicle) then
|
|
local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle)
|
|
|
|
for i=maxSeats - 1, 0, -1 do
|
|
if IsVehicleSeatFree(vehicle, i) then
|
|
freeSeat = i
|
|
break
|
|
end
|
|
end
|
|
|
|
if freeSeat then
|
|
TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat)
|
|
dragStatus.isDragged = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx_policejob:OutVehicle')
|
|
AddEventHandler('esx_policejob:OutVehicle', function()
|
|
local playerPed = PlayerPedId()
|
|
|
|
if IsPedSittingInAnyVehicle(playerPed) then
|
|
local vehicle = GetVehiclePedIsIn(playerPed, false)
|
|
TaskLeaveVehicle(playerPed, vehicle, 16)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent('esx_policejob:updateBlip')
|
|
AddEventHandler('esx_policejob:updateBlip', function()
|
|
|
|
-- Refresh all blips
|
|
for k, existingBlip in pairs(self.BlipsCops) do
|
|
RemoveBlip(existingBlip)
|
|
end
|
|
|
|
-- Clean the blip table
|
|
self.BlipsCops = {}
|
|
|
|
-- Enable blip?
|
|
if self.Config.EnableESXService and not playerInService then
|
|
return
|
|
end
|
|
|
|
if not self.Config.EnableJobBlip then
|
|
return
|
|
end
|
|
|
|
-- Is the player a cop? In that case show all the blips for other cops
|
|
if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then
|
|
ESX.TriggerServerCallback('esx_society:getOnlinePlayers', function(players)
|
|
for i=1, #players, 1 do
|
|
if players[i].job.name == 'police' then
|
|
local id = GetPlayerFromServerId(players[i].source)
|
|
if NetworkIsPlayerActive(id) and GetPlayerPed(id) ~= PlayerPedId() then
|
|
CreateBlip(id)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
end)
|
|
|
|
AddEventHandler('playerSpawned', function(spawn)
|
|
isDead = false
|
|
TriggerEvent('esx_policejob:unrestrain')
|
|
|
|
if not hasAlreadyJoined then
|
|
TriggerServerEvent('esx_policejob:spawned')
|
|
end
|
|
hasAlreadyJoined = true
|
|
end)
|
|
|
|
AddEventHandler('esx:onPlayerDeath', function(data)
|
|
isDead = true
|
|
end)
|
|
|
|
AddEventHandler('onResourceStop', function(resource)
|
|
if resource == GetCurrentResourceName() then
|
|
TriggerEvent('esx_policejob:unrestrain')
|
|
TriggerEvent('esx_phone:removeSpecialContact', 'police')
|
|
|
|
if self.Config.EnableESXService then
|
|
TriggerServerEvent('esx_service:disableService', 'police')
|
|
end
|
|
|
|
if self.Config.EnableHandcuffTimer and self.HandcuffTimer.active then
|
|
ESX.ClearTimeout(self.HandcuffTimer.task)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Key Controls
|
|
Input.On('released', Input.Groups.MOVE, Input.Controls.PICKUP, function(lastPressed)
|
|
|
|
if self.CurrentAction and self.IsPolice() then
|
|
self.CurrentAction()
|
|
self.CurrentAction = nil
|
|
end
|
|
|
|
end)
|
|
|
|
Input.On('released', Input.Groups.MOVE, Input.Controls.SELECT_CHARACTER_FRANKLIN, function(lastPressed)
|
|
|
|
if (not self.IsDead) and self.IsPolice() and (not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions')) then
|
|
|
|
if not self.Config.EnableESXService then
|
|
OpenPoliceActionsMenu()
|
|
elseif playerInService then
|
|
OpenPoliceActionsMenu()
|
|
else
|
|
ESX.ShowNotification(_U('job_police:service_not'))
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
Input.On('released', Input.Groups.MOVE, Input.Controls.PICKUP, function(lastPressed)
|
|
|
|
if self.CurrentAction and self.IsPolice() and self.CurrentTask.busy then
|
|
|
|
ESX.ShowNotification(_U('job_police:impound_canceled'))
|
|
ESX.ClearTimeout(self.CurrentTask.task)
|
|
ClearPedTasks(PlayerPedId())
|
|
|
|
self.CurrentTask.busy = false
|
|
|
|
end
|
|
|
|
end)
|