From 57d8abed3d40cace143a77a70731c56330f4fdc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20N=27gadi?= Date: Tue, 8 Aug 2017 20:16:19 +0200 Subject: [PATCH] Add files --- README.md | 28 + __resource.lua | 14 + client/main.lua | 1430 +++++++++++++++++++++++++++++++++++++ config.lua | 77 ++ esx_policejob_full.sql | 18 + esx_policejob_minimal.sql | 10 + server/main.lua | 263 +++++++ 7 files changed, 1840 insertions(+) create mode 100644 __resource.lua create mode 100644 client/main.lua create mode 100644 config.lua create mode 100644 esx_policejob_full.sql create mode 100644 esx_policejob_minimal.sql create mode 100644 server/main.lua diff --git a/README.md b/README.md index e5f1f919..0c536d16 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,30 @@ # fxserver-esx_policejob FXServer ESX Police Job + +[REQUIREMENTS] + +* Auto mode + * esx_billing => https://github.com/FXServer-ESX/fxserver-esx_billing + +* Player management (boss actions and armory with buyable weapons) + * esx_society => https://github.com/FXServer-ESX/fxserver-esx_society + * esx_datastore => https://github.com/FXServer-ESX/fxserver-esx_datastore + +[INSTALLATION] + +1) CD in your resources/[esx] folder +2) Clone the repository +``` +git clone https://github.com/FXServer-ESX/fxserver-esx_taxijob esx_taxijob +``` +3) * Auto mode : Import esx_policejob_minimal.sql in your database + * Player / Armory management : Import esx_policejob_full.sql in your database + +4) Add this in your server.cfg : + +``` +start esx_policejob +``` +5) * If you want player management you have to set Config.EnablePlayerManagement to true in config.lua + * If you want armory management you have to set Config.EnableArmoryManagement to true in config.lua + diff --git a/__resource.lua b/__resource.lua new file mode 100644 index 00000000..d486b6f5 --- /dev/null +++ b/__resource.lua @@ -0,0 +1,14 @@ +resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' + +description 'ESX Police Job' + +server_scripts { + '@mysql-async/lib/MySQL.lua', + 'config.lua', + 'server/main.lua' +} + +client_scripts { + 'config.lua', + 'client/main.lua' +} diff --git a/client/main.lua b/client/main.lua new file mode 100644 index 00000000..618fd401 --- /dev/null +++ b/client/main.lua @@ -0,0 +1,1430 @@ +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 +} + +ESX = nil +local PlayerData = {} +local GUI = {} +GUI.Time = 0 +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 + +Citizen.CreateThread(function() + while ESX == nil do + TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) + Citizen.Wait(0) + end +end) + +function SetVehicleMaxMods(vehicle) + + local props = { + modEngine = 2, + modBrakes = 2, + modTransmission = 2, + modSuspension = 3, + modTurbo = true, + } + + ESX.Game.SetVehicleProperties(vehicle, props) + +end + +function OpenCloakroomMenu() + + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'cloakroom', + { + title = 'Vestiaire', + align = 'top-left', + elements = { + {label = 'Tenue Civil', value = 'citizen_wear'}, + {label = 'Tenue Policier', value = 'police_wear'}, + }, + }, + function(data, menu) + + menu.close() + + if data.current.value == 'citizen_wear' then + + ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) + TriggerEvent('skinchanger:loadSkin', skin) + end) + + end + + if data.current.value == 'police_wear' then + + ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) + + if skin.sex == 0 then + TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male) + else + TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female) + end + + end) + + end + + CurrentAction = 'menu_cloakroom' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour vous changer' + CurrentActionData = {} + + end, + function(data, menu) + + menu.close() + + CurrentAction = 'menu_cloakroom' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour vous changer' + CurrentActionData = {} + end + ) + +end + +function OpenArmoryMenu(station) + + if Config.EnableArmoryManagement then + + local elements = { + {label = 'Prendre Arme', value = 'get_weapon'}, + {label = 'Déposer Arme', value = 'put_weapon'} + } + + if PlayerData.job.grade_name == 'boss' then + table.insert(elements, {label = 'Acheter Armes', value = 'buy_weapons'}) + end + + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'armory', + { + title = 'Armurerie', + 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 + + end, + function(data, menu) + + menu.close() + + CurrentAction = 'menu_armory' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour accéder à l\'armurerie' + 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 = 'Armurerie', + 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 = 'Appuez sur ~INPUT_CONTEXT~ pour accéder à l\'armurerie' + CurrentActionData = {station = station} + + end + ) + + end + +end + +function OpenVehicleSpawnerMenu(station, partNum) + + local elements = {} + local vehicles = Config.PoliceStations[station].Vehicles + + for i=1, #Config.PoliceStations[station].AuthorizedVehicles, 1 do + local vehicle = Config.PoliceStations[station].AuthorizedVehicles[i] + table.insert(elements, {label = vehicle.label, value = vehicle.name}) + end + + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'vehicle_spawner', + { + title = 'Véhicule', + align = 'top-left', + elements = elements, + }, + function(data, menu) + + menu.close() + + local model = data.current.value + + local vehicle, distance = ESX.Game.GetClosestVehicle({ + x = vehicles[partNum].SpawnPoint.x, + y = vehicles[partNum].SpawnPoint.y, + z = vehicles[partNum].SpawnPoint.z + }) + + if distance > 3.0 then + + local playerPed = GetPlayerPed(-1) + + 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('Service complet : ' .. inServiceCount .. '/' .. maxInService) + end + + end, 'police') + + end + + else + ESX.ShowNotification('Il y a déja un véhicule de sorti') + end + + end, + function(data, menu) + + menu.close() + + CurrentAction = 'menu_vehicle_spawner' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour sortir un véhicule' + CurrentActionData = {station = station, partNum = partNum} + + end + ) + +end + +function OpenPoliceActionsMenu() + + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'police_actions', + { + title = 'Police', + align = 'top-left', + elements = { + {label = 'Interaction citoyen', value = 'citizen_interaction'}, + {label = 'Interaction véhicule', value = 'vehicle_interaction'}, + {label = 'Placer objets', value = 'object_spawner'}, + }, + }, + function(data, menu) + + if data.current.value == 'citizen_interaction' then + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'citizen_interaction', + { + title = 'Interaction Csitoyen', + align = 'top-left', + elements = { + {label = 'Carte d\'identité', value = 'identity_card'}, + {label = 'Fouiller', value = 'body_search'}, + {label = 'Menotter / Démenotter', value = 'handcuff'}, + {label = 'Mettre dans véhicule', value = 'put_in_vehicle'}, + {label = 'Amende', value = 'fine'} + }, + }, + function(data2, menu2) + + local player, distance = ESX.Game.GetClosestPlayer() + + if distance ~= -1 and distance <= 3.0 then + + if data2.current.value == 'identity_card' then + OpenIdentityCardMenu(player) + end + + if data2.current.value == 'body_search' then + OpenBodySearchMenu(player) + end + + if data2.current.value == 'handcuff' then + TriggerServerEvent('esx_policejob:handcuff', GetPlayerServerId(player)) + end + + if data2.current.value == 'put_in_vehicle' then + TriggerServerEvent('esx_policejob:putInVehicle', GetPlayerServerId(player)) + end + + if data2.current.value == 'fine' then + OpenFineMenu(player) + end + + else + ESX.ShowNotification('Aucun joueur à proximité') + end + + end, + function(data2, menu2) + menu2.close() + end + ) + + end + + if data.current.value == 'vehicle_interaction' then + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'vehicle_interaction', + { + title = 'Interaction Csitoyen', + align = 'top-left', + elements = { + {label = 'Infos véhicule', value = 'vehicle_infos'}, + {label = 'Crocheter véhicule', value = 'hijack_vehicle'}, + }, + }, + function(data2, menu2) + + local vehicle, distance = ESX.Game.GetClosestVehicle() + + if distance ~= -1 and distance <= 3.0 then + + local vehicleData = ESX.Game.GetVehicleProperties(vehicle) + + if data2.current.value == 'vehicle_infos' then + OpenVehicleInfosMenu(vehicleData) + end + + if data2.current.value == 'hijack_vehicle' then + + local playerPed = GetPlayerPed(-1) + local coords = GetEntityCoords(playerPed) + + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then + + local vehicle, distance = ESX.Game.GetClosestVehicle({ + x = coords.x, + y = coords.y, + z = coords.z + }) + + if DoesEntityExist(vehicle) then + + Citizen.CreateThread(function() + + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_WELDING", 0, true) + + Wait(20000) + + ClearPedTasksImmediately(playerPed) + + SetVehicleDoorsLocked(vehicle, 1) + SetVehicleDoorsLockedForAllPlayers(vehicle, false) + + TriggerEvent('esx:showNotification', 'Véhicule ~g~déverouillé~s~') + + end) + + end + + end + + end + + else + ESX.ShowNotification('Aucun véhicule à proximité') + end + + end, + function(data2, menu2) + menu2.close() + end + ) + + end + + if data.current.value == 'object_spawner' then + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'citizen_interaction', + { + title = 'Interaction Csitoyen', + align = 'top-left', + elements = { + {label = 'Plot', value = 'prop_roadcone02a'}, + {label = 'Barrière', value = 'prop_barrier_work06a'}, + {label = 'Herse', value = 'p_ld_stinger_s'}, + {label = 'Caisse', value = 'prop_boxpile_07d'}, + {label = 'Caisse', value = 'hei_prop_cash_crate_half_full'} + }, + }, + function(data2, menu2) + + + local model = data2.current.value + local playerPed = GetPlayerPed(-1) + 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 + }, 3.0, 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 jobLabel = nil + + if data.job.grade_label ~= nil and data.job.grade_label ~= '' then + jobLabel = 'Job : ' .. data.job.label .. ' - ' .. data.job.grade_label + else + jobLabel = 'Job : ' .. data.job.label + end + + local elements = { + {label = 'Nom : ' .. data.name, value = nil}, + {label = jobLabel, value = nil}, + } + + if data.drunk ~= nil then + table.insert(elements, {label = 'Alcoolémie : ' .. data.drunk .. '%', value = nil}) + end + + if data.licenses ~= nil then + + table.insert(elements, {label = '--- Licenses ---', 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 = 'Interaction Citoyen', + 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 = {} + + local blackMoney = 0 + + for i=1, #data.accounts, 1 do + if data.accounts[i].name == 'black_money' then + blackMoney = data.accounts[i].money + end + end + + table.insert(elements, { + label = 'Confisquer argent sale : $' .. blackMoney, + value = 'black_money', + itemType = 'item_account', + amount = blackMoney + }) + + table.insert(elements, {label = '--- Armes ---', value = nil}) + + for i=1, #data.weapons, 1 do + table.insert(elements, { + label = 'Confisquer ' .. ESX.GetWeaponLabel(data.weapons[i].name), + value = data.weapons[i].name, + itemType = 'item_weapon', + amount = data.ammo, + }) + end + + table.insert(elements, {label = '--- Inventaire ---', value = nil}) + + for i=1, #data.inventory, 1 do + if data.inventory[i].count > 0 then + table.insert(elements, { + label = 'Confisquer x' .. 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 = 'Fouille', + 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 = 'Amende', + align = 'top-left', + elements = { + {label = 'Code de la route', value = 0}, + {label = 'Délit mineur', value = 1}, + {label = 'Délit moyen', value = 2}, + {label = 'Délit grave', 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 = 'Amende', + 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', 'Amende : ' .. label, amount) + else + TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), '', 'Amende : ' .. label, amount) + end + + ESX.SetTimeout(300, function() + OpenFineCategoryMenu(player, category) + end) + + end, + function(data, menu) + menu.close() + end + ) + + end, category) + +end + +function OpenVehicleInfosMenu(vehicleData) + + ESX.TriggerServerCallback('esx_policejob:getVehicleInfos', function(infos) + + local elements = {} + + table.insert(elements, {label = 'N°: ' .. infos.plate, value = nil}) + + if infos.owner == nil then + table.insert(elements, {label = 'Propriétaire : Inconnu', value = nil}) + else + table.insert(elements, {label = 'Propriétaire : ' .. infos.owner, value = nil}) + end + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'vehicle_infos', + { + title = 'Infos Véhicule', + 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 = 'Armurerie - Prendre Arme', + 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 = GetPlayerPed(-1) + 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 = 'Armurerie - Déposer Arme', + align = 'top-left', + elements = elements, + }, + function(data, menu) + + menu.close() + + ESX.TriggerServerCallback('esx_policejob:addArmoryWeapon', function() + OpenPutWeaponMenu() + end, data.current.value) + + 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 = 'Armurerie - Acheter Armes', + 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) + else + ESX.ShowNotification('Vous n\'avez pas assez d\'argent') + end + + end, data.current.price) + + end, + function(data, menu) + menu.close() + end + ) + + end) + +end + +function OpenBossActionsMenu() + + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open( + 'default', GetCurrentResourceName(), 'realestateagent', + { + title = PlayerData.job.grade_label, + elements = { + {label = 'Retirer argent société', value = 'withdraw_society_money'}, + {label = 'Déposer argent', value = 'deposit_money'}, + } + }, + function(data, menu) + + if data.current.value == 'withdraw_society_money' then + + ESX.UI.Menu.Open( + 'dialog', GetCurrentResourceName(), 'withdraw_society_money_amount', + { + title = 'Montant du retrait' + }, + function(data, menu) + + local amount = tonumber(data.value) + + if amount == nil then + ESX.ShowNotification('Montant invalide') + else + menu.close() + TriggerServerEvent('esx_society:withdrawMoney', 'police', amount) + end + + end, + function(data, menu) + menu.close() + end + ) + + end + + if data.current.value == 'deposit_money' then + + ESX.UI.Menu.Open( + 'dialog', GetCurrentResourceName(), 'deposit_money_amount', + { + title = 'Montant du dépôt' + }, + function(data, menu) + + local amount = tonumber(data.value) + + if amount == nil then + ESX.ShowNotification('Montant invalide') + else + menu.close() + TriggerServerEvent('esx_society:depositMoney', 'police', amount) + end + + end, + function(data, menu) + menu.close() + end + ) + + end + + end, + function(data, menu) + + menu.close() + + CurrentAction = 'menu_boss_actions' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour ouvrir le menu' + CurrentActionData = {} + + end + ) + +end + +RegisterNetEvent('esx:playerLoaded') +AddEventHandler('esx:playerLoaded', function(xPlayer) + PlayerData = xPlayer +end) + +RegisterNetEvent('esx:setJob') +AddEventHandler('esx:setJob', function(job) + PlayerData.job = job +end) + +AddEventHandler('esx_policejob:hasEnteredMarker', function(station, part, partNum) + + if part == 'Cloakroom' then + CurrentAction = 'menu_cloakroom' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour vous changer' + CurrentActionData = {} + end + + if part == 'Armory' then + CurrentAction = 'menu_armory' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour accéder à l\'armurerie' + CurrentActionData = {station = station} + end + + if part == 'VehicleSpawner' then + CurrentAction = 'menu_vehicle_spawner' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour sortir un véhicule' + CurrentActionData = {station = station, partNum = partNum} + end + + if part == 'HelicopterSpawner' then + + local helicopters = Config.PoliceStations[station].Helicopters + + local vehicle, distance = ESX.Game.GetClosestVehicle({ + x = helicopters[partNum].SpawnPoint.x, + y = helicopters[partNum].SpawnPoint.y, + z = helicopters[partNum].SpawnPoint.z + }) + + if distance > 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 = GetPlayerPed(-1) + + if IsPedInAnyVehicle(playerPed, false) then + + local vehicle, distance = ESX.Game.GetClosestVehicle() + + if distance <= 2.0 then + CurrentAction = 'delete_vehicle' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour ranger le véhicule' + CurrentActionData = {vehicle = vehicle} + end + + end + + end + + if part == 'BossActions' then + CurrentAction = 'menu_boss_actions' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour ouvrir le menu' + CurrentActionData = {} + end + +end) + +AddEventHandler('esx_policejob:hasExitedMarker', function(station, part, partNum) + CurrentAction = nil +end) + +AddEventHandler('esx_policejob:hasEnteredEntityZone', function(entity) + + local playerPed = GetPlayerPed(-1) + + if PlayerData.job ~= nil and PlayerData.job.name == 'police' and not IsPedInAnyVehicle(playerPed, false) then + CurrentAction = 'remove_entity' + CurrentActionMsg = 'Appuez sur ~INPUT_CONTEXT~ pour enlever l\'objet' + CurrentActionData = {entity = entity} + end + + if GetEntityModel(entity) == GetHashKey('p_ld_stinger_s') then + + local playerPed = GetPlayerPed(-1) + local coords = GetEntityCoords(playerPed) + + if IsPedInAnyVehicle(playerPed, false) then + + local vehicle, distance = ESX.Game.GetClosestVehicle({ + x = coords.x, + y = coords.y, + z = coords.z + }) + + if distance <= 1.0 then + + for i=0, 7, 1 do + SetVehicleTyreBurst(vehicle, i, true, 1000) + end + + 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 = GetPlayerPed(-1) + + Citizen.CreateThread(function() + + 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) + SetEnableHandcuffs(playerPed, true) + SetPedCanPlayGestureAnims(playerPed, false) + FreezeEntityPosition(playerPed, true) + + else + + ClearPedSecondaryTask(playerPed) + SetEnableHandcuffs(playerPed, false) + SetPedCanPlayGestureAnims(playerPed, true) + FreezeEntityPosition(playerPed, false) + + end + + end) +end) + +RegisterNetEvent('esx_policejob:putInVehicle') +AddEventHandler('esx_policejob:putInVehicle', function() + + local playerPed = GetPlayerPed(-1) + local coords = GetEntityCoords(playerPed) + + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then + + local vehicle, distance = ESX.Game.GetClosestVehicle({ + x = coords.x, + y = coords.y, + z = coords.z + }) + + 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) + end + + end + + end + +end) + +-- Handcuff +Citizen.CreateThread(function() + while true do + Wait(0) + if IsHandcuffed then + DisableControlAction(0, 142, true) -- MeleeAttackAlternate + DisableControlAction(0, 30, true) -- MoveLeftRight + DisableControlAction(0, 31, true) -- MoveUpDown + 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, 60) + SetBlipDisplay(blip, 4) + SetBlipScale (blip, 1.2) + SetBlipColour (blip, v.Blip.Color) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentString("Commissariat") + 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 = GetPlayerPed(-1) + 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 = GetPlayerPed(-1) + 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() + while true do + + Citizen.Wait(0) + + local playerPed = GetPlayerPed(-1) + local coords = GetEntityCoords(playerPed) + + local entity, distance = ESX.Game.GetClosestObject({ + 'prop_roadcone02a', + 'prop_barrier_work06a', + 'p_ld_stinger_s', + 'prop_boxpile_07d', + 'hei_prop_cash_crate_half_full' + }) + + if distance ~= -1 and distance <= 3.0 then + + if LastEntity ~= entity then + TriggerEvent('esx_policejob:hasEnteredEntityZone', entity) + LastEntity = entity + 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 IsControlPressed(0, Keys['E']) and PlayerData.job ~= nil and PlayerData.job.name == 'police' and (GetGameTimer() - GUI.Time) > 150 then + + if CurrentAction == 'menu_cloakroom' then + OpenCloakroomMenu() + end + + if CurrentAction == 'menu_armory' then + OpenArmoryMenu(CurrentActionData.station) + end + + if CurrentAction == 'menu_vehicle_spawner' then + OpenVehicleSpawnerMenu(CurrentActionData.station, CurrentActionData.partNum) + end + + if CurrentAction == 'delete_vehicle' then + + 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 + + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + end + + if CurrentAction == 'menu_boss_actions' then + OpenBossActionsMenu() + end + + if CurrentAction == 'remove_entity' then + DeleteEntity(CurrentActionData.entity) + end + + CurrentAction = nil + GUI.Time = GetGameTimer() + + end + + end + + if IsControlPressed(0, Keys['F6']) and PlayerData.job ~= nil and PlayerData.job.name == 'police' and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions') and (GetGameTimer() - GUI.Time) > 150 then + OpenPoliceActionsMenu() + GUI.Time = GetGameTimer() + end + + end +end) diff --git a/config.lua b/config.lua new file mode 100644 index 00000000..00e67176 --- /dev/null +++ b/config.lua @@ -0,0 +1,77 @@ +Config = {} +Config.DrawDistance = 100.0 +Config.MarkerType = 1 +Config.MarkerSize = {x = 1.5, y = 1.5, z = 1.0} +Config.MarkerColor = {r = 50, g = 50, b = 204} +Config.EnablePlayerManagement = false +Config.EnableArmoryManagement = false +Config.MaxInService = -1 + +Config.PoliceStations = { + + LSPD = { + + Blip = { + Pos = {x = 425.130, y = -979.558, z = 30.711}, + Color = 29 + }, + + AuthorizedWeapons = { + {name = 'WEAPON_NIGHTSTICK', price = 200}, + {name = 'WEAPON_COMBATPISTOL', price = 300}, + {name = 'WEAPON_ASSAULTSMG', price = 1250}, + {name = 'WEAPON_ASSAULTRIFLE', price = 1500}, + {name = 'WEAPON_PUMPSHOTGUN', price = 600}, + {name = 'WEAPON_STUNGUN', price = 500}, + {name = 'WEAPON_FLASHLIGHT', price = 80}, + {name = 'WEAPON_FIREEXTINGUISHER', price = 120}, + {name = 'WEAPON_FLAREGUN', price = 60}, + {name = 'WEAPON_STICKYBOMB', price = 250}, + {name = 'GADGET_PARACHUTE', price = 300}, + }, + + AuthorizedVehicles = { + {name = 'police' , label = 'Véhicule de patrouille 1'}, + {name = 'police2', label = 'Véhicule de patrouille 2'}, + {name = 'police3', label = 'Véhicule de patrouille 3'}, + {name = 'police4', label = 'Véhicule civil'}, + {name = 'policeb', label = 'Moto'}, + {name = 'policet', label = 'Van de transport'}, + }, + + Cloakrooms = { + {x = 452.600, y = -993.306, z = 29.750} + }, + + Armories = { + {x = 451.699, y = -980.356, z = 29.689} + }, + + Vehicles = { + { + Spawner = {x = 454.69, y = -1017.4, z = 27.430}, + SpawnPoint = {x = 438.42, y = -1018.3, z = 27.757}, + Heading = 90.0 + } + }, + + Helicopters = { + { + Spawner = {x = 466.477, y = -982.819, z = 42.691}, + SpawnPoint = {x = 450.04, y = -981.14, z = 42.691}, + Heading = 0.0 + } + }, + + VehicleDeleters = { + {x = 462.74, y = -1014.4, z = 27.065}, + {x = 462.40, y = -1019.7, z = 27.104} + }, + + BossActions = { + {x = 448.417, y = -973.208, z = 29.689} + } + + } + +} \ No newline at end of file diff --git a/esx_policejob_full.sql b/esx_policejob_full.sql new file mode 100644 index 00000000..543a5801 --- /dev/null +++ b/esx_policejob_full.sql @@ -0,0 +1,18 @@ +INSERT INTO `addon_account` (name, label, shared) VALUES + ('society_police','Police',1) +; + +INSERT INTO `datastore` (name, label, shared) VALUES + ('society_police','Police',1) +; + +INSERT INTO `jobs` (name, label) VALUES + ('police','LSPD') +; + +INSERT INTO `job_grades` (job_name, grade, name, label, salary, skin_male, skin_female) VALUES + ('police',0,'recrue','Recrue',20,'{\"tshirt_1\":57,\"torso_1\":55,\"arms\":0,\"pants_1\":35,\"glasses\":0,\"decals_2\":0,\"hair_color_2\":0,\"helmet_2\":0,\"hair_color_1\":5,\"face\":19,\"glasses_2\":1,\"torso_2\":0,\"shoes\":24,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"pants_2\":0,\"hair_2\":0,\"decals_1\":0,\"tshirt_2\":0,\"helmet_1\":8}','{\"tshirt_1\":34,\"torso_1\":48,\"shoes\":24,\"pants_1\":34,\"torso_2\":0,\"decals_2\":0,\"hair_color_2\":0,\"glasses\":0,\"helmet_2\":0,\"hair_2\":3,\"face\":21,\"decals_1\":0,\"glasses_2\":1,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"pants_2\":0,\"arms\":14,\"hair_color_1\":10,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',1,'sergeant','Sergent',40,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":1,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"arms\":0,\"decals_1\":8,\"torso_2\":0,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"hair_color_1\":5,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":14,\"pants_1\":34,\"pants_2\":0,\"decals_2\":1,\"hair_color_2\":0,\"shoes\":24,\"helmet_2\":0,\"hair_2\":3,\"decals_1\":7,\"torso_2\":0,\"face\":21,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"glasses_2\":1,\"hair_color_1\":10,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',2,'lieutenant','Lieutenant',65,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":2,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"glasses\":0,\"decals_1\":8,\"hair_color_1\":5,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"torso_2\":0,\"arms\":41,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":44,\"pants_1\":34,\"hair_2\":3,\"decals_2\":2,\"hair_color_2\":0,\"hair_color_1\":10,\"helmet_2\":0,\"face\":21,\"shoes\":24,\"torso_2\":0,\"glasses_2\":1,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"pants_2\":0,\"decals_1\":7,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',3,'commandant','Commandant',80,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":3,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"arms\":41,\"torso_2\":0,\"hair_color_1\":5,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"decals_1\":8,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":44,\"pants_1\":34,\"pants_2\":0,\"decals_2\":3,\"hair_color_2\":0,\"face\":21,\"helmet_2\":0,\"hair_2\":3,\"decals_1\":7,\"torso_2\":0,\"hair_color_1\":10,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"glasses_2\":1,\"shoes\":24,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}') +; diff --git a/esx_policejob_minimal.sql b/esx_policejob_minimal.sql new file mode 100644 index 00000000..fca6635c --- /dev/null +++ b/esx_policejob_minimal.sql @@ -0,0 +1,10 @@ +INSERT INTO `jobs` (name, label) VALUES + ('police','LSPD') +; + +INSERT INTO `job_grades` (job_name, grade, name, label, salary, skin_male, skin_female) VALUES + ('police',0,'recrue','Recrue',20,'{\"tshirt_1\":57,\"torso_1\":55,\"arms\":0,\"pants_1\":35,\"glasses\":0,\"decals_2\":0,\"hair_color_2\":0,\"helmet_2\":0,\"hair_color_1\":5,\"face\":19,\"glasses_2\":1,\"torso_2\":0,\"shoes\":24,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"pants_2\":0,\"hair_2\":0,\"decals_1\":0,\"tshirt_2\":0,\"helmet_1\":8}','{\"tshirt_1\":34,\"torso_1\":48,\"shoes\":24,\"pants_1\":34,\"torso_2\":0,\"decals_2\":0,\"hair_color_2\":0,\"glasses\":0,\"helmet_2\":0,\"hair_2\":3,\"face\":21,\"decals_1\":0,\"glasses_2\":1,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"pants_2\":0,\"arms\":14,\"hair_color_1\":10,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',1,'sergeant','Sergent',40,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":1,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"arms\":0,\"decals_1\":8,\"torso_2\":0,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"hair_color_1\":5,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":14,\"pants_1\":34,\"pants_2\":0,\"decals_2\":1,\"hair_color_2\":0,\"shoes\":24,\"helmet_2\":0,\"hair_2\":3,\"decals_1\":7,\"torso_2\":0,\"face\":21,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"glasses_2\":1,\"hair_color_1\":10,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',2,'lieutenant','Lieutenant',65,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":2,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"glasses\":0,\"decals_1\":8,\"hair_color_1\":5,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"torso_2\":0,\"arms\":41,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":44,\"pants_1\":34,\"hair_2\":3,\"decals_2\":2,\"hair_color_2\":0,\"hair_color_1\":10,\"helmet_2\":0,\"face\":21,\"shoes\":24,\"torso_2\":0,\"glasses_2\":1,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"pants_2\":0,\"decals_1\":7,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}'), + ('police',3,'commandant','Commandant',80,'{\"tshirt_1\":58,\"torso_1\":55,\"shoes\":24,\"pants_1\":35,\"pants_2\":0,\"decals_2\":3,\"hair_color_2\":0,\"face\":19,\"helmet_2\":0,\"hair_2\":0,\"arms\":41,\"torso_2\":0,\"hair_color_1\":5,\"hair_1\":2,\"skin\":34,\"sex\":0,\"glasses_1\":0,\"glasses_2\":1,\"decals_1\":8,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":11}','{\"tshirt_1\":35,\"torso_1\":48,\"arms\":44,\"pants_1\":34,\"pants_2\":0,\"decals_2\":3,\"hair_color_2\":0,\"face\":21,\"helmet_2\":0,\"hair_2\":3,\"decals_1\":7,\"torso_2\":0,\"hair_color_1\":10,\"hair_1\":11,\"skin\":34,\"sex\":1,\"glasses_1\":5,\"glasses_2\":1,\"shoes\":24,\"glasses\":0,\"tshirt_2\":0,\"helmet_1\":57}') +; diff --git a/server/main.lua b/server/main.lua new file mode 100644 index 00000000..11ace9c4 --- /dev/null +++ b/server/main.lua @@ -0,0 +1,263 @@ +ESX = nil + +TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) + +if Config.MaxInService ~= -1 then + TriggerEvent('esx_service:activateService', 'police', Config.MaxInService) +end + +RegisterServerEvent('esx_policejob:giveWeapon') +AddEventHandler('esx_policejob:giveWeapon', function(weapon, ammo) + local xPlayer = ESX.GetPlayerFromId(source) + xPlayer.addWeapon(weapon, ammo) +end) + +RegisterServerEvent('esx_policejob:confiscatePlayerItem') +AddEventHandler('esx_policejob:confiscatePlayerItem', function(target, itemType, itemName, amount) + + local sourceXPlayer = ESX.GetPlayerFromId(source) + local targetXPlayer = ESX.GetPlayerFromId(target) + + if itemType == 'item_standard' then + + local label = sourceXPlayer.getInventoryItem(itemName).label + + targetXPlayer.removeInventoryItem(itemName, amount) + sourceXPlayer.addInventoryItem(itemName, amount) + + TriggerClientEvent('esx:showNotification', sourceXPlayer.source, 'Vous avez confisqué ~y~x' .. amount .. ' ' .. label .. '~s~ à ~b~' .. targetXPlayer.name) + TriggerClientEvent('esx:showNotification', targetXPlayer.source, '~b~' .. targetXPlayer.name .. '~s~ vous a confisqué ~y~x' .. amount .. ' ' .. label ) + + end + + if itemType == 'item_account' then + + targetXPlayer.removeAccountMoney(itemName, amount) + sourceXPlayer.addAccountMoney(itemName, amount) + + TriggerClientEvent('esx:showNotification', sourceXPlayer.source, 'Vous avez confisqué ~y~$' .. amount .. '~s~ à ~b~' .. targetXPlayer.name) + TriggerClientEvent('esx:showNotification', targetXPlayer.source, '~b~' .. targetXPlayer.name .. '~s~ vous a confisqué ~y~$' .. amount) + + end + + if itemType == 'item_weapon' then + + targetXPlayer.removeWeapon(itemName) + sourceXPlayer.addWeapon(itemName, amount) + + TriggerClientEvent('esx:showNotification', sourceXPlayer.source, 'Vous avez confisqué ~y~x1 ' .. ESX.GetWeaponLabel(itemName) .. '~s~ à ~b~' .. targetXPlayer.name) + TriggerClientEvent('esx:showNotification', targetXPlayer.source, '~b~' .. targetXPlayer.name .. '~s~ vous a confisqué ~y~x1 ' .. ESX.GetWeaponLabel(itemName)) + + end + +end) + +RegisterServerEvent('esx_policejob:handcuff') +AddEventHandler('esx_policejob:handcuff', function(target) + TriggerClientEvent('esx_policejob:handcuff', target) +end) + +RegisterServerEvent('esx_policejob:putInVehicle') +AddEventHandler('esx_policejob:putInVehicle', function(target) + TriggerClientEvent('esx_policejob:putInVehicle', target) +end) + +ESX.RegisterServerCallback('esx_policejob:getOtherPlayerData', function(source, cb, target) + + local xPlayer = ESX.GetPlayerFromId(target) + + local data = { + name = GetPlayerName(source), + job = xPlayer.job, + inventory = xPlayer.inventory, + accounts = xPlayer.accounts, + weapons = xPlayer.loadout + } + + TriggerEvent('esx_status:getStatus', _source, 'drunk', function(status) + data.drunk = status:getPercent() + end) + + TriggerEvent('esx_license:getLicenses', _source, function(licenses) + data.licenses = licenses + end) + + cb(data) + +end) + +ESX.RegisterServerCallback('esx_policejob:getFineList', function(source, cb, category) + + MySQL.Async.fetchAll( + 'SELECT * FROM fine_types WHERE category = @category', + { + ['@category'] = category + }, + function(fines) + cb(fines) + end + ) + +end) + +ESX.RegisterServerCallback('esx_policejob:getVehicleInfos', function(source, cb, plate) + + MySQL.Async.fetchAll( + 'SELECT * FROM owned_vehicles', + {}, + function(result) + + local foundIdentifier = nil + + for i=1, #result, 1 do + + local vehicleData = json.decode(result[i].vehicle) + + if vehicleData.plate == plate then + foundIdentifier = result[i].owner + break + end + + end + + if foundIdentifier ~= nil then + + MySQL.Async.fetchAll( + 'SELECT * FROM users WHERE identifier = @identifier', + { + ['@identifier'] = foundIdentifier + }, + function(result) + + local infos = { + plate = plate, + owner = result[1].name + } + + cb(infos) + + end + ) + + else + + local infos = { + plate = plate + } + + cb(infos) + + end + + end + ) + +end) + +ESX.RegisterServerCallback('esx_policejob:getArmoryWeapons', function(source, cb) + + TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store) + + local weapons = store.get('weapons') + + if weapons == nil then + weapons = {} + end + + cb(weapons) + + end) + +end) + +ESX.RegisterServerCallback('esx_policejob:addArmoryWeapon', function(source, cb, weaponName) + + local xPlayer = ESX.GetPlayerFromId(source) + + xPlayer.removeWeapon(weaponName) + + TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store) + + local weapons = store.get('weapons') + + if weapons == nil then + weapons = {} + end + + local foundWeapon = false + + for i=1, #weapons, 1 do + if weapons[i].name == weaponName then + weapons[i].count = weapons[i].count + 1 + foundWeapon = true + end + end + + if not foundWeapon then + table.insert(weapons, { + name = weaponName, + count = 1 + }) + end + + store.set('weapons', weapons) + + cb() + + end) + +end) + +ESX.RegisterServerCallback('esx_policejob:removeArmoryWeapon', function(source, cb, weaponName) + + local xPlayer = ESX.GetPlayerFromId(source) + + xPlayer.addWeapon(weaponName, 1000) + + TriggerEvent('esx_datastore:getSharedDataStore', 'society_police', function(store) + + local weapons = store.get('weapons') + + if weapons == nil then + weapons = {} + end + + local foundWeapon = false + + for i=1, #weapons, 1 do + if weapons[i].name == weaponName then + weapons[i].count = (weapons[i].count > 0 and weapons[i].count - 1 or 0) + foundWeapon = true + end + end + + if not foundWeapon then + table.insert(weapons, { + name = weaponName, + count = 0 + }) + end + + store.set('weapons', weapons) + + cb() + + end) + +end) + + +ESX.RegisterServerCallback('esx_policejob:buy', function(source, cb, amount) + + TriggerEvent('esx_addonaccount:getSharedAccount', 'society_police', function(account) + + if account.money >= amount then + account.removeMoney(amount) + cb(true) + else + cb(false) + end + + end) + +end) \ No newline at end of file