Discord + +Copyright (C) 2024 bitpredator + +This program Is free software: you can redistribute it And/Or modify it under the terms Of the GNU General Public License As published by the Free Software Foundation, either version 3 Of the License, Or (at your option) any later version. + +This program Is distributed In the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty Of MERCHANTABILITY Or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License For more details. + +ATTENTION: +You are not authorized to change the name of the resource and the resources within it. + +If you want to contribute you can open a pull request. + +You are not authorized to sell this software (this is free project). + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/esx_billing/esx_billing.sql b/server-data/resources/[bpt_addons]/bpt_billing/bpt_billing.sql similarity index 99% rename from server-data/resources/[esx_addons]/esx_billing/esx_billing.sql rename to server-data/resources/[bpt_addons]/bpt_billing/bpt_billing.sql index 63fb743f1..731a3d3f7 100644 --- a/server-data/resources/[esx_addons]/esx_billing/esx_billing.sql +++ b/server-data/resources/[bpt_addons]/bpt_billing/bpt_billing.sql @@ -9,4 +9,3 @@ CREATE TABLE `billing` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - diff --git a/server-data/resources/[esx_addons]/esx_billing/client/main.lua b/server-data/resources/[bpt_addons]/bpt_billing/client/main.lua similarity index 60% rename from server-data/resources/[esx_addons]/esx_billing/client/main.lua rename to server-data/resources/[bpt_addons]/bpt_billing/client/main.lua index fbe03be5f..145f48678 100644 --- a/server-data/resources/[esx_addons]/esx_billing/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_billing/client/main.lua @@ -1,27 +1,27 @@ local isDead = false function ShowBillsMenu() - ESX.TriggerServerCallback("esx_billing:getBills", function(bills) + ESX.TriggerServerCallback("bpt_billing:getBills", function(bills) if #bills > 0 then local elements = { - { unselectable = true, icon = "fas fa-scroll", title = _U("invoices") }, + { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("invoices") }, } for _, v in ipairs(bills) do elements[#elements + 1] = { icon = "fas fa-scroll", - title = ('%s - %s'):format(v.label, _U("invoices_item", ESX.Math.GroupDigits(v.amount))), + title = ('%s - %s'):format(v.label, TranslateCap("invoices_item", ESX.Math.GroupDigits(v.amount))), billId = v.id, } end - ESX.OpenContext("right", elements, function(_, element) - ESX.TriggerServerCallback("esx_billing:payBill", function() + ESX.OpenContext("right", elements, function(menu, element) + ESX.TriggerServerCallback("bpt_billing:payBill", function() ShowBillsMenu() end, element.billId) end) else - ESX.ShowNotification(_U("no_invoices")) + ESX.ShowNotification(TranslateCap("no_invoices")) end end) end @@ -32,11 +32,11 @@ RegisterCommand("showbills", function() end end, false) -RegisterKeyMapping("showbills", _U("keymap_showbills"), "keyboard", "F7") +RegisterKeyMapping("showbills", TranslateCap("keymap_showbills"), "keyboard", "F7") AddEventHandler("esx:onPlayerDeath", function() isDead = true end) -AddEventHandler("esx:onPlayerSpawn", function() +AddEventHandler("esx:onPlayerSpawn", function(spawn) isDead = false end) diff --git a/server-data/resources/[esx_addons]/esx_billing/config.lua b/server-data/resources/[bpt_addons]/bpt_billing/config.lua similarity index 100% rename from server-data/resources/[esx_addons]/esx_billing/config.lua rename to server-data/resources/[bpt_addons]/bpt_billing/config.lua diff --git a/server-data/resources/[esx_addons]/esx_billing/fxmanifest.lua b/server-data/resources/[bpt_addons]/bpt_billing/fxmanifest.lua similarity index 87% rename from server-data/resources/[esx_addons]/esx_billing/fxmanifest.lua rename to server-data/resources/[bpt_addons]/bpt_billing/fxmanifest.lua index 392d876d4..2bb4f02eb 100644 --- a/server-data/resources/[esx_addons]/esx_billing/fxmanifest.lua +++ b/server-data/resources/[bpt_addons]/bpt_billing/fxmanifest.lua @@ -2,7 +2,7 @@ fx_version("adamant") game("gta5") -description("ESX Billing") +description("Allows Players to recieve and Send Bills") lua54("yes") version("1.0.0") diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/en.lua b/server-data/resources/[bpt_addons]/bpt_billing/locales/en.lua similarity index 100% rename from server-data/resources/[esx_addons]/esx_billing/locales/en.lua rename to server-data/resources/[bpt_addons]/bpt_billing/locales/en.lua diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/it.lua b/server-data/resources/[bpt_addons]/bpt_billing/locales/it.lua similarity index 100% rename from server-data/resources/[esx_addons]/esx_billing/locales/it.lua rename to server-data/resources/[bpt_addons]/bpt_billing/locales/it.lua diff --git a/server-data/resources/[esx_addons]/esx_billing/server/main.lua b/server-data/resources/[bpt_addons]/bpt_billing/server/main.lua similarity index 70% rename from server-data/resources/[esx_addons]/esx_billing/server/main.lua rename to server-data/resources/[bpt_addons]/bpt_billing/server/main.lua index 6ae75ea07..3458cc6c1 100644 --- a/server-data/resources/[esx_addons]/esx_billing/server/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_billing/server/main.lua @@ -1,135 +1,135 @@ -RegisterNetEvent("esx_billing:sendBill", function(playerId, sharedAccountName, label, amount) - local xPlayer = ESX.GetPlayerFromId(source) - local xTarget = ESX.GetPlayerFromId(playerId) - amount = ESX.Math.Round(amount) - - if amount > 0 and xTarget then - if string.match(sharedAccountName, "society_") then - local jobName = string.gsub(sharedAccountName, "society_", "") - if xPlayer.job.name ~= jobName then - print(("[^2ERROR^7] Player ^5%s^7 Attempted to Send bill from a society (^5%s^7), but does not have the correct Job - Possibly Cheats"):format(xPlayer.source, sharedAccountName)) - return - end - TriggerEvent("bpt_addonaccount:getSharedAccount", sharedAccountName, function(account) - if account then - MySQL.insert("INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)", { xTarget.identifier, xPlayer.identifier, "society", sharedAccountName, label, amount }, function() - xTarget.showNotification(_U("received_invoice")) - end) - else - print(("[^2ERROR^7] Player ^5%s^7 Attempted to Send bill from invalid society - ^5%s^7"):format(xPlayer.source, sharedAccountName)) - end - end) - else - MySQL.insert("INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)", { xTarget.identifier, xPlayer.identifier, "player", xPlayer.identifier, label, amount }, function() - xTarget.showNotification(_U("received_invoice")) - end) - end - end -end) - -ESX.RegisterServerCallback("esx_billing:getBills", function(source, cb) - local xPlayer = ESX.GetPlayerFromId(source) - - MySQL.query("SELECT amount, id, label FROM billing WHERE identifier = ?", { xPlayer.identifier }, function(result) - cb(result) - end) -end) - -ESX.RegisterServerCallback("esx_billing:getTargetBills", function(_, cb, target) - local xPlayer = ESX.GetPlayerFromId(target) - - if xPlayer then - MySQL.query("SELECT amount, id, label FROM billing WHERE identifier = ?", { xPlayer.identifier }, function(result) - cb(result) - end) - else - cb({}) - end -end) - -ESX.RegisterServerCallback("esx_billing:payBill", function(source, cb, billId) - local xPlayer = ESX.GetPlayerFromId(source) - - MySQL.single("SELECT sender, target_type, target, amount FROM billing WHERE id = ?", { billId }, function(result) - if result then - local amount = result.amount - local xTarget = ESX.GetPlayerFromIdentifier(result.sender) - - if result.target_type == "player" then - if xTarget then - if xPlayer.getMoney() >= amount then - MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) - if rowsChanged == 1 then - xPlayer.removeMoney(amount, "Bill Paid") - xTarget.addMoney(amount, "Paid bill") - - xPlayer.showNotification(_U("paid_invoice", ESX.Math.GroupDigits(amount))) - xTarget.showNotification(_U("received_payment", ESX.Math.GroupDigits(amount))) - end - - cb() - end) - elseif xPlayer.getAccount("bank").money >= amount then - MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) - if rowsChanged == 1 then - xPlayer.removeAccountMoney("bank", amount, "Bill Paid") - xTarget.addAccountMoney("bank", amount, "Paid bill") - - xPlayer.showNotification(_U("paid_invoice", ESX.Math.GroupDigits(amount))) - xTarget.showNotification(_U("received_payment", ESX.Math.GroupDigits(amount))) - end - - cb() - end) - else - xTarget.showNotification(_U("target_no_money")) - xPlayer.showNotification(_U("no_money")) - cb() - end - else - xPlayer.showNotification(_U("player_not_online")) - cb() - end - else - TriggerEvent("bpt_addonaccount:getSharedAccount", result.target, function(account) - if xPlayer.getMoney() >= amount then - MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) - if rowsChanged == 1 then - xPlayer.removeMoney(amount, "Bill Paid") - account.addMoney(amount) - - xPlayer.showNotification(_U("paid_invoice", ESX.Math.GroupDigits(amount))) - if xTarget then - xTarget.showNotification(_U("received_payment", ESX.Math.GroupDigits(amount))) - end - end - - cb() - end) - elseif xPlayer.getAccount("bank").money >= amount then - MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) - if rowsChanged == 1 then - xPlayer.removeAccountMoney("bank", amount, "Bill Paid") - account.addMoney(amount) - xPlayer.showNotification(_U("paid_invoice", ESX.Math.GroupDigits(amount))) - - if xTarget then - xTarget.showNotification(_U("received_payment", ESX.Math.GroupDigits(amount))) - end - end - - cb() - end) - else - if xTarget then - xTarget.showNotification(_U("target_no_money")) - end - - xPlayer.showNotification(_U("no_money")) - cb() - end - end) - end - end - end) -end) +RegisterNetEvent("bpt_billing:sendBill", function(playerId, sharedAccountName, label, amount) + local xPlayer = ESX.GetPlayerFromId(source) + local xTarget = ESX.GetPlayerFromId(playerId) + amount = ESX.Math.Round(amount) + + if amount > 0 and xTarget then + if string.match(sharedAccountName, "society_") then + local jobName = string.gsub(sharedAccountName, "society_", "") + if xPlayer.job.name ~= jobName then + print(("[^2ERROR^7] Player ^5%s^7 Attempted to Send bill from a society (^5%s^7), but does not have the correct Job - Possibly Cheats"):format(xPlayer.source, sharedAccountName)) + return + end + TriggerEvent("bpt_addonaccount:getSharedAccount", sharedAccountName, function(account) + if account then + MySQL.insert("INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)", { xTarget.identifier, xPlayer.identifier, "society", sharedAccountName, label, amount }, function(rowsChanged) + xTarget.showNotification(TranslateCap("received_invoice")) + end) + else + print(("[^2ERROR^7] Player ^5%s^7 Attempted to Send bill from invalid society - ^5%s^7"):format(xPlayer.source, sharedAccountName)) + end + end) + else + MySQL.insert("INSERT INTO billing (identifier, sender, target_type, target, label, amount) VALUES (?, ?, ?, ?, ?, ?)", { xTarget.identifier, xPlayer.identifier, "player", xPlayer.identifier, label, amount }, function(rowsChanged) + xTarget.showNotification(TranslateCap("received_invoice")) + end) + end + end +end) + +ESX.RegisterServerCallback("bpt_billing:getBills", function(source, cb) + local xPlayer = ESX.GetPlayerFromId(source) + + MySQL.query("SELECT amount, id, label FROM billing WHERE identifier = ?", { xPlayer.identifier }, function(result) + cb(result) + end) +end) + +ESX.RegisterServerCallback("bpt_billing:getTargetBills", function(source, cb, target) + local xPlayer = ESX.GetPlayerFromId(target) + + if xPlayer then + MySQL.query("SELECT amount, id, label FROM billing WHERE identifier = ?", { xPlayer.identifier }, function(result) + cb(result) + end) + else + cb({}) + end +end) + +ESX.RegisterServerCallback("bpt_billing:payBill", function(source, cb, billId) + local xPlayer = ESX.GetPlayerFromId(source) + + MySQL.single("SELECT sender, target_type, target, amount FROM billing WHERE id = ?", { billId }, function(result) + if result then + local amount = result.amount + local xTarget = ESX.GetPlayerFromIdentifier(result.sender) + + if result.target_type == "player" then + if xTarget then + if xPlayer.getMoney() >= amount then + MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) + if rowsChanged == 1 then + xPlayer.removeMoney(amount, "Bill Paid") + xTarget.addMoney(amount, "Paid bill") + + xPlayer.showNotification(TranslateCap("paid_invoice", ESX.Math.GroupDigits(amount))) + xTarget.showNotification(TranslateCap("received_payment", ESX.Math.GroupDigits(amount))) + end + + cb() + end) + elseif xPlayer.getAccount("bank").money >= amount then + MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) + if rowsChanged == 1 then + xPlayer.removeAccountMoney("bank", amount, "Bill Paid") + xTarget.addAccountMoney("bank", amount, "Paid bill") + + xPlayer.showNotification(TranslateCap("paid_invoice", ESX.Math.GroupDigits(amount))) + xTarget.showNotification(TranslateCap("received_payment", ESX.Math.GroupDigits(amount))) + end + + cb() + end) + else + xTarget.showNotification(TranslateCap("target_no_money")) + xPlayer.showNotification(TranslateCap("no_money")) + cb() + end + else + xPlayer.showNotification(TranslateCap("player_not_online")) + cb() + end + else + TriggerEvent("bpt_addonaccount:getSharedAccount", result.target, function(account) + if xPlayer.getMoney() >= amount then + MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) + if rowsChanged == 1 then + xPlayer.removeMoney(amount, "Bill Paid") + account.addMoney(amount) + + xPlayer.showNotification(TranslateCap("paid_invoice", ESX.Math.GroupDigits(amount))) + if xTarget then + xTarget.showNotification(TranslateCap("received_payment", ESX.Math.GroupDigits(amount))) + end + end + + cb() + end) + elseif xPlayer.getAccount("bank").money >= amount then + MySQL.update("DELETE FROM billing WHERE id = ?", { billId }, function(rowsChanged) + if rowsChanged == 1 then + xPlayer.removeAccountMoney("bank", amount, "Bill Paid") + account.addMoney(amount) + xPlayer.showNotification(TranslateCap("paid_invoice", ESX.Math.GroupDigits(amount))) + + if xTarget then + xTarget.showNotification(TranslateCap("received_payment", ESX.Math.GroupDigits(amount))) + end + end + + cb() + end) + else + if xTarget then + xTarget.showNotification(TranslateCap("target_no_money")) + end + + xPlayer.showNotification(TranslateCap("no_money")) + cb() + end + end) + end + end + end) +end) diff --git a/server-data/resources/[bpt_addons]/bpt_dustman/client/main.lua b/server-data/resources/[bpt_addons]/bpt_dustman/client/main.lua index c5abef28b..e64feb87b 100644 --- a/server-data/resources/[bpt_addons]/bpt_dustman/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_dustman/client/main.lua @@ -4,440 +4,375 @@ local LastZone RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(xPlayer) - ESX.PlayerData = xPlayer - ESX.PlayerLoaded = true + ESX.PlayerData = xPlayer + ESX.PlayerLoaded = true end) RegisterNetEvent("esx:onPlayerLogout") AddEventHandler("esx:onPlayerLogout", function() - ESX.PlayerLoaded = false - ESX.PlayerData = {} + ESX.PlayerLoaded = false + ESX.PlayerData = {} end) RegisterNetEvent("esx:setJob") AddEventHandler("esx:setJob", function(job) - ESX.PlayerData.job = job + ESX.PlayerData.job = job end) function DrawSub(msg, time) - ClearPrints() - BeginTextCommandPrint("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandPrint(time, 1) + ClearPrints() + BeginTextCommandPrint("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandPrint(time, 1) end function ShowLoadingPromt(msg, time, type) - CreateThread(function() - Wait(0) + CreateThread(function() + Wait(0) - BeginTextCommandBusyspinnerOn("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandBusyspinnerOn(type) - Wait(time) + BeginTextCommandBusyspinnerOn("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandBusyspinnerOn(type) + Wait(time) - BusyspinnerOff() - end) + BusyspinnerOff() + end) end function OpenCloakroom() - local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, - { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, - { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "wear_citizen" then - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - end) - elseif element.value == "wear_work" 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 - ESX.CloseContext() - end, function() - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, + { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, + { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "wear_citizen" then + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + elseif element.value == "wear_work" 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 + ESX.CloseContext() + end, function() + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end) end function OpenVehicleSpawnerMenu() - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, - } - - if Config.EnableSocietyOwnedVehicles then - ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) - if #vehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #vehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", - value = vehicles[i], - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - local vehicleProps = element.value - ESX.TriggerServerCallback("bpt_dustmanjob:SpawnVehicle", function() - return - end, vehicleProps.model, vehicleProps) - TriggerServerEvent("esx_society:removeVehicleFromGarage", "dustman", vehicleProps) - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end, "dustman") - else -- not society vehicles - if #Config.AuthorizedVehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #Config.AuthorizedVehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = Config.AuthorizedVehicles[i].label, - value = Config.AuthorizedVehicles[i].model, - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - ESX.TriggerServerCallback("bpt_dustmanjob:SpawnVehicle", function() - ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") - end, element.value, { plate = "DUSTMAN" }) - ESX.CloseContext() - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, + } + + if Config.EnableSocietyOwnedVehicles then + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) + if #vehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #vehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + local vehicleProps = element.value + ESX.TriggerServerCallback("bpt_dustmanjob:SpawnVehicle", function() + return + end, vehicleProps.model, vehicleProps) + TriggerServerEvent("esx_society:removeVehicleFromGarage", "dustman", vehicleProps) + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end, "dustman") + else -- not society vehicles + if #Config.AuthorizedVehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #Config.AuthorizedVehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = Config.AuthorizedVehicles[i].label, + value = Config.AuthorizedVehicles[i].model, + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + ESX.TriggerServerCallback("bpt_dustmanjob:SpawnVehicle", function() + ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") + end, element.value, { plate = "DUSTMAN" }) + ESX.CloseContext() + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end end function DeleteJobVehicle() - if Config.EnableSocietyOwnedVehicles then - local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent("esx_society:putVehicleInGarage", "dustman", vehicleProps) - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - else - if IsInAuthorizedVehicle() then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - - if Config.MaxInService ~= -1 then - TriggerServerEvent("esx_service:disableService", "dustman") - end - else - ESX.ShowNotification(TranslateCap("only_dustman")) - end - end + if Config.EnableSocietyOwnedVehicles then + local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) + TriggerServerEvent("esx_society:putVehicleInGarage", "dustman", vehicleProps) + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + else + if IsInAuthorizedVehicle() then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + + if Config.MaxInService ~= -1 then + TriggerServerEvent("esx_service:disableService", "dustman") + end + else + ESX.ShowNotification(TranslateCap("only_dustman")) + end + end end function OpenDustmanActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-dustman", title = TranslateCap("dustman") }, - { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, - { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then - elements[#elements + 1] = { - icon = "fas fa-wallet", - title = TranslateCap("boss_actions"), - value = "boss_actions", - } - end - - ESX.OpenContext("right", elements, function(_, element) - if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then - exports.ox_inventory:openInventory("stash", "society_dustman") - return ESX.CloseContext() - elseif element.value == "put_stock" then - OpenPutStocksMenu() - elseif element.value == "get_stock" then - OpenGetStocksMenu() - elseif element.value == "boss_actions" then - TriggerEvent("esx_society:openBossMenu", "dustman", function(_, menu) - menu.close() - end) - end - end, function() - CurrentAction = "dustman_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-dustman", title = TranslateCap("dustman") }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then + elements[#elements + 1] = { + icon = "fas fa-wallet", + title = TranslateCap("boss_actions"), + value = "boss_actions", + } + end + + ESX.OpenContext("right", elements, function(_, element) + if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_dustman") + return ESX.CloseContext() + elseif element.value == "put_stock" then + OpenPutStocksMenu() + elseif element.value == "get_stock" then + OpenGetStocksMenu() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "dustman", function(_, menu) + menu.close() + end) + end + end, function() + CurrentAction = "dustman_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + end) end function OpenMobileDustmanActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-dustman", title = TranslateCap("dustman") }, - { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "billing" then - local elements2 = { - { unselectable = true, icon = "fas fa-dustman", title = element.title }, - { - title = TranslateCap("amount"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 250000, - inputPlaceholder = TranslateCap("bill_amount"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2) - local amount = tonumber(menu2.eles[2].inputValue) - if amount == nil then - ESX.ShowNotification(TranslateCap("amount_invalid")) - else - ESX.CloseContext() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap("no_players_near")) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(closestPlayer), - "society_dustman", - "Dustman", - amount - ) - ESX.ShowNotification(TranslateCap("billing_sent")) - end - end - end) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-dustman", title = TranslateCap("dustman") }, + { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "billing" then + local elements2 = { + { unselectable = true, icon = "fas fa-dustman", title = element.title }, + { + title = TranslateCap("amount"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 250000, + inputPlaceholder = TranslateCap("bill_amount"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2) + local amount = tonumber(menu2.eles[2].inputValue) + if amount == nil then + ESX.ShowNotification(TranslateCap("amount_invalid")) + else + ESX.CloseContext() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players_near")) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_dustman", "Dustman", amount) + ESX.ShowNotification(TranslateCap("billing_sent")) + end + end + end) + end + end) end function IsInAuthorizedVehicle() - local playerPed = PlayerPedId() - local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) + local playerPed = PlayerPedId() + local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) - for i = 1, #Config.AuthorizedVehicles, 1 do - if vehModel == joaat(Config.AuthorizedVehicles[i].model) then - return true - end - end + for i = 1, #Config.AuthorizedVehicles, 1 do + if vehModel == joaat(Config.AuthorizedVehicles[i].model) then + return true + end + end - return false + return false end AddEventHandler("bpt_dustmanjob:hasEnteredMarker", function(zone) - if zone == "VehicleSpawner" then - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - elseif zone == "VehicleDeleter" then - local playerPed = PlayerPedId() - local vehicle = GetVehiclePedIsIn(playerPed, false) - - if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then - CurrentAction = "delete_vehicle" - CurrentActionMsg = TranslateCap("store_veh") - CurrentActionData = { - vehicle = vehicle, - } - end - elseif zone == "DustmanActions" then - CurrentAction = "dustman_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - elseif zone == "Cloakroom" then - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end + if zone == "VehicleSpawner" then + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + elseif zone == "VehicleDeleter" then + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("store_veh") + CurrentActionData = { + vehicle = vehicle, + } + end + elseif zone == "DustmanActions" then + CurrentAction = "dustman_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + elseif zone == "Cloakroom" then + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end end) AddEventHandler("bpt_dustmanjob:hasExitedMarker", function() - ESX.CloseContext() - CurrentAction = nil + ESX.CloseContext() + CurrentAction = nil end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord( - Config.Zones.DustmanActions.Pos.x, - Config.Zones.DustmanActions.Pos.y, - Config.Zones.DustmanActions.Pos.z - ) - - SetBlipSprite(blip, 67) - SetBlipDisplay(blip, 4) - SetBlipScale(blip, 1.0) - SetBlipColour(blip, 21) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("blip_dustman")) - EndTextCommandSetBlipName(blip) + local blip = AddBlipForCoord(Config.Zones.DustmanActions.Pos.x, Config.Zones.DustmanActions.Pos.y, Config.Zones.DustmanActions.Pos.z) + + SetBlipSprite(blip, 67) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 21) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("blip_dustman")) + EndTextCommandSetBlipName(blip) end) -- Enter / Exit marker events, and draw markers CreateThread(function() - while true do - local sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == "dustman" then - local coords = GetEntityCoords(PlayerPedId()) - local isInMarker, currentZone = false - local inVeh = IsPedInAnyVehicle(PlayerPedId()) - - for k, v in pairs(Config.Zones) do - local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) - local distance = #(coords - zonePos) - - if v.Type ~= -1 and distance < Config.DrawDistance then - sleep = 0 - if k == "VehicleDeleter" then - if inVeh then - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - else - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - end - - if distance < v.Size.x then - isInMarker, currentZone = true, k - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker, LastZone = true, currentZone - TriggerEvent("bpt_dustmanjob:hasEnteredMarker", currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent("bpt_dustmanjob:hasExitedMarker", LastZone) - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if ESX.PlayerData.job and ESX.PlayerData.job.name == "dustman" then + local coords = GetEntityCoords(PlayerPedId()) + local isInMarker, currentZone = false + local inVeh = IsPedInAnyVehicle(PlayerPedId()) + + for k, v in pairs(Config.Zones) do + local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) + local distance = #(coords - zonePos) + + if v.Type ~= -1 and distance < Config.DrawDistance then + sleep = 0 + if k == "VehicleDeleter" then + if inVeh then + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + else + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + end + + if distance < v.Size.x then + isInMarker, currentZone = true, k + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker, LastZone = true, currentZone + TriggerEvent("bpt_dustmanjob:hasEnteredMarker", currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("bpt_dustmanjob:hasExitedMarker", LastZone) + end + end + Wait(sleep) + end end) -- Key Controls CreateThread(function() - while true do - local sleep = 1500 - if CurrentAction and not ESX.PlayerData.dead then - sleep = 0 - ESX.ShowHelpNotification(CurrentActionMsg) - - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "dustman" then - if CurrentAction == "dustman_actions_menu" then - OpenDustmanActionsMenu() - elseif CurrentAction == "cloakroom" then - OpenCloakroom() - elseif CurrentAction == "vehicle_spawner" then - OpenVehicleSpawnerMenu() - elseif CurrentAction == "delete_vehicle" then - DeleteJobVehicle() - end - - CurrentAction = nil - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if CurrentAction and not ESX.PlayerData.dead then + sleep = 0 + ESX.ShowHelpNotification(CurrentActionMsg) + + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "dustman" then + if CurrentAction == "dustman_actions_menu" then + OpenDustmanActionsMenu() + elseif CurrentAction == "cloakroom" then + OpenCloakroom() + elseif CurrentAction == "vehicle_spawner" then + OpenVehicleSpawnerMenu() + elseif CurrentAction == "delete_vehicle" then + DeleteJobVehicle() + end + + CurrentAction = nil + end + end + Wait(sleep) + end end) RegisterCommand("dustmanmenu", function() - if - not ESX.PlayerData.dead - and Config.EnablePlayerManagement - and ESX.PlayerData.job - and ESX.PlayerData.job.name == "dustman" - then - OpenMobileDustmanActionsMenu() - end + if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == "dustman" then + OpenMobileDustmanActionsMenu() + end end, false) RegisterKeyMapping("dustmanmenu", "Open Dustman Menu", "keyboard", "f6") diff --git a/server-data/resources/[bpt_addons]/bpt_fisherman/client/main.lua b/server-data/resources/[bpt_addons]/bpt_fisherman/client/main.lua index 7a1df1af3..6f57833d3 100644 --- a/server-data/resources/[bpt_addons]/bpt_fisherman/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_fisherman/client/main.lua @@ -4,436 +4,371 @@ local LastZone RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(xPlayer) - ESX.PlayerData = xPlayer - ESX.PlayerLoaded = true + ESX.PlayerData = xPlayer + ESX.PlayerLoaded = true end) RegisterNetEvent("esx:onPlayerLogout") AddEventHandler("esx:onPlayerLogout", function() - ESX.PlayerLoaded = false - ESX.PlayerData = {} + ESX.PlayerLoaded = false + ESX.PlayerData = {} end) RegisterNetEvent("esx:setJob") AddEventHandler("esx:setJob", function(job) - ESX.PlayerData.job = job + ESX.PlayerData.job = job end) function DrawSub(msg, time) - ClearPrints() - BeginTextCommandPrint("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandPrint(time, 1) + ClearPrints() + BeginTextCommandPrint("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandPrint(time, 1) end function ShowLoadingPromt(msg, time, type) - CreateThread(function() - Wait(0) + CreateThread(function() + Wait(0) - BeginTextCommandBusyspinnerOn("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandBusyspinnerOn(type) - Wait(time) + BeginTextCommandBusyspinnerOn("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandBusyspinnerOn(type) + Wait(time) - BusyspinnerOff() - end) + BusyspinnerOff() + end) end function OpenCloakroom() - local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, - { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, - { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "wear_citizen" then - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - end) - elseif element.value == "wear_work" 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 - ESX.CloseContext() - end, function() - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, + { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, + { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "wear_citizen" then + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + elseif element.value == "wear_work" 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 + ESX.CloseContext() + end, function() + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end) end function OpenVehicleSpawnerMenu() - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, - } - - if Config.EnableSocietyOwnedVehicles then - ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) - if #vehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #vehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", - value = vehicles[i], - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - local vehicleProps = element.value - ESX.TriggerServerCallback("bpt_fishermanjob:SpawnVehicle", function() - return - end, vehicleProps.model, vehicleProps) - TriggerServerEvent("esx_society:removeVehicleFromGarage", "fisherman", vehicleProps) - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end, "fisherman") - else -- not society vehicles - if #Config.AuthorizedVehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #Config.AuthorizedVehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = Config.AuthorizedVehicles[i].label, - value = Config.AuthorizedVehicles[i].model, - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - ESX.TriggerServerCallback("bpt_fishermanjob:SpawnVehicle", function() - ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") - end, element.value, { plate = "FISH JOB" }) - ESX.CloseContext() - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, + } + + if Config.EnableSocietyOwnedVehicles then + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) + if #vehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #vehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + local vehicleProps = element.value + ESX.TriggerServerCallback("bpt_fishermanjob:SpawnVehicle", function() + return + end, vehicleProps.model, vehicleProps) + TriggerServerEvent("esx_society:removeVehicleFromGarage", "fisherman", vehicleProps) + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end, "fisherman") + else -- not society vehicles + if #Config.AuthorizedVehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #Config.AuthorizedVehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = Config.AuthorizedVehicles[i].label, + value = Config.AuthorizedVehicles[i].model, + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + ESX.TriggerServerCallback("bpt_fishermanjob:SpawnVehicle", function() + ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") + end, element.value, { plate = "FISH JOB" }) + ESX.CloseContext() + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end end function DeleteJobVehicle() - if Config.EnableSocietyOwnedVehicles then - local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent("esx_society:putVehicleInGarage", "fisherman", vehicleProps) - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - else - if IsInAuthorizedVehicle() then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - else - ESX.ShowNotification(TranslateCap("only_fisherman")) - end - end + if Config.EnableSocietyOwnedVehicles then + local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) + TriggerServerEvent("esx_society:putVehicleInGarage", "fisherman", vehicleProps) + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + else + if IsInAuthorizedVehicle() then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + else + ESX.ShowNotification(TranslateCap("only_fisherman")) + end + end end function OpenFishermanActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-fisherman", title = TranslateCap("fisherman") }, - { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, - { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then - elements[#elements + 1] = { - icon = "fas fa-wallet", - title = TranslateCap("boss_actions"), - value = "boss_actions", - } - end - - ESX.OpenContext("right", elements, function(_, element) - if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then - exports.ox_inventory:openInventory("stash", "society_fisherman") - return ESX.CloseContext() - elseif element.value == "put_stock" then - OpenPutStocksMenu() - elseif element.value == "get_stock" then - OpenGetStocksMenu() - elseif element.value == "boss_actions" then - TriggerEvent("esx_society:openBossMenu", "fisherman", function(_, menu) - menu.close() - end) - end - end, function() - CurrentAction = "fisherman_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-fisherman", title = TranslateCap("fisherman") }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then + elements[#elements + 1] = { + icon = "fas fa-wallet", + title = TranslateCap("boss_actions"), + value = "boss_actions", + } + end + + ESX.OpenContext("right", elements, function(_, element) + if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_fisherman") + return ESX.CloseContext() + elseif element.value == "put_stock" then + OpenPutStocksMenu() + elseif element.value == "get_stock" then + OpenGetStocksMenu() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "fisherman", function(_, menu) + menu.close() + end) + end + end, function() + CurrentAction = "fisherman_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + end) end function OpenMobileFishermanActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-fisherman", title = TranslateCap("fisherman") }, - { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "billing" then - local elements2 = { - { unselectable = true, icon = "fas fa-fisherman", title = element.title }, - { - title = TranslateCap("amount"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 250000, - inputPlaceholder = TranslateCap("bill_amount"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2) - local amount = tonumber(menu2.eles[2].inputValue) - if amount == nil then - ESX.ShowNotification(TranslateCap("amount_invalid")) - else - ESX.CloseContext() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap("no_players_near")) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(closestPlayer), - "society_fisherman", - "Fisherman", - amount - ) - ESX.ShowNotification(TranslateCap("billing_sent")) - end - end - end) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-fisherman", title = TranslateCap("fisherman") }, + { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "billing" then + local elements2 = { + { unselectable = true, icon = "fas fa-fisherman", title = element.title }, + { + title = TranslateCap("amount"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 250000, + inputPlaceholder = TranslateCap("bill_amount"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2) + local amount = tonumber(menu2.eles[2].inputValue) + if amount == nil then + ESX.ShowNotification(TranslateCap("amount_invalid")) + else + ESX.CloseContext() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players_near")) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_fisherman", "Fisherman", amount) + ESX.ShowNotification(TranslateCap("billing_sent")) + end + end + end) + end + end) end function IsInAuthorizedVehicle() - local playerPed = PlayerPedId() - local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) + local playerPed = PlayerPedId() + local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) - for i = 1, #Config.AuthorizedVehicles, 1 do - if vehModel == joaat(Config.AuthorizedVehicles[i].model) then - return true - end - end + for i = 1, #Config.AuthorizedVehicles, 1 do + if vehModel == joaat(Config.AuthorizedVehicles[i].model) then + return true + end + end - return false + return false end AddEventHandler("bpt_fishermanjob:hasEnteredMarker", function(zone) - if zone == "VehicleSpawner" then - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - elseif zone == "VehicleDeleter" then - local playerPed = PlayerPedId() - local vehicle = GetVehiclePedIsIn(playerPed, false) - - if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then - CurrentAction = "delete_vehicle" - CurrentActionMsg = TranslateCap("store_veh") - CurrentActionData = { - vehicle = vehicle, - } - end - elseif zone == "FishermanActions" then - CurrentAction = "fisherman_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - elseif zone == "Cloakroom" then - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end + if zone == "VehicleSpawner" then + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + elseif zone == "VehicleDeleter" then + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("store_veh") + CurrentActionData = { + vehicle = vehicle, + } + end + elseif zone == "FishermanActions" then + CurrentAction = "fisherman_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + elseif zone == "Cloakroom" then + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end end) AddEventHandler("bpt_fishermanjob:hasExitedMarker", function() - ESX.CloseContext() - CurrentAction = nil + ESX.CloseContext() + CurrentAction = nil end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord( - Config.Zones.FishermanActions.Pos.x, - Config.Zones.FishermanActions.Pos.y, - Config.Zones.FishermanActions.Pos.z - ) - - SetBlipSprite(blip, 478) - SetBlipDisplay(blip, 4) - SetBlipScale(blip, 1.0) - SetBlipColour(blip, 21) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("blip_fisherman")) - EndTextCommandSetBlipName(blip) + local blip = AddBlipForCoord(Config.Zones.FishermanActions.Pos.x, Config.Zones.FishermanActions.Pos.y, Config.Zones.FishermanActions.Pos.z) + + SetBlipSprite(blip, 478) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 21) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("blip_fisherman")) + EndTextCommandSetBlipName(blip) end) -- Enter / Exit marker events, and draw markers CreateThread(function() - while true do - local sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == "fisherman" then - local coords = GetEntityCoords(PlayerPedId()) - local isInMarker, currentZone = false - local inVeh = IsPedInAnyVehicle(PlayerPedId()) - - for k, v in pairs(Config.Zones) do - local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) - local distance = #(coords - zonePos) - - if v.Type ~= -1 and distance < Config.DrawDistance then - sleep = 0 - if k == "VehicleDeleter" then - if inVeh then - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - else - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - end - - if distance < v.Size.x then - isInMarker, currentZone = true, k - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker, LastZone = true, currentZone - TriggerEvent("bpt_fishermanjob:hasEnteredMarker", currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent("bpt_fishermanjob:hasExitedMarker", LastZone) - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if ESX.PlayerData.job and ESX.PlayerData.job.name == "fisherman" then + local coords = GetEntityCoords(PlayerPedId()) + local isInMarker, currentZone = false + local inVeh = IsPedInAnyVehicle(PlayerPedId()) + + for k, v in pairs(Config.Zones) do + local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) + local distance = #(coords - zonePos) + + if v.Type ~= -1 and distance < Config.DrawDistance then + sleep = 0 + if k == "VehicleDeleter" then + if inVeh then + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + else + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + end + + if distance < v.Size.x then + isInMarker, currentZone = true, k + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker, LastZone = true, currentZone + TriggerEvent("bpt_fishermanjob:hasEnteredMarker", currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("bpt_fishermanjob:hasExitedMarker", LastZone) + end + end + Wait(sleep) + end end) -- Key Controls CreateThread(function() - while true do - local sleep = 1500 - if CurrentAction and not ESX.PlayerData.dead then - sleep = 0 - ESX.ShowHelpNotification(CurrentActionMsg) - - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "fisherman" then - if CurrentAction == "fisherman_actions_menu" then - OpenFishermanActionsMenu() - elseif CurrentAction == "cloakroom" then - OpenCloakroom() - elseif CurrentAction == "vehicle_spawner" then - OpenVehicleSpawnerMenu() - elseif CurrentAction == "delete_vehicle" then - DeleteJobVehicle() - end - - CurrentAction = nil - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if CurrentAction and not ESX.PlayerData.dead then + sleep = 0 + ESX.ShowHelpNotification(CurrentActionMsg) + + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "fisherman" then + if CurrentAction == "fisherman_actions_menu" then + OpenFishermanActionsMenu() + elseif CurrentAction == "cloakroom" then + OpenCloakroom() + elseif CurrentAction == "vehicle_spawner" then + OpenVehicleSpawnerMenu() + elseif CurrentAction == "delete_vehicle" then + DeleteJobVehicle() + end + + CurrentAction = nil + end + end + Wait(sleep) + end end) RegisterCommand("fishermanmenu", function() - if - not ESX.PlayerData.dead - and Config.EnablePlayerManagement - and ESX.PlayerData.job - and ESX.PlayerData.job.name == "fisherman" - then - OpenMobileFishermanActionsMenu() - end + if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == "fisherman" then + OpenMobileFishermanActionsMenu() + end end, false) RegisterKeyMapping("fishermanmenu", "Open Fisherman Menu", "keyboard", "f6") diff --git a/server-data/resources/[bpt_addons]/bpt_importjob/client/main.lua b/server-data/resources/[bpt_addons]/bpt_importjob/client/main.lua index 3f0f105ce..e5066328d 100644 --- a/server-data/resources/[bpt_addons]/bpt_importjob/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_importjob/client/main.lua @@ -4,440 +4,375 @@ local LastZone RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(xPlayer) - ESX.PlayerData = xPlayer - ESX.PlayerLoaded = true + ESX.PlayerData = xPlayer + ESX.PlayerLoaded = true end) RegisterNetEvent("esx:onPlayerLogout") AddEventHandler("esx:onPlayerLogout", function() - ESX.PlayerLoaded = false - ESX.PlayerData = {} + ESX.PlayerLoaded = false + ESX.PlayerData = {} end) RegisterNetEvent("esx:setJob") AddEventHandler("esx:setJob", function(job) - ESX.PlayerData.job = job + ESX.PlayerData.job = job end) function DrawSub(msg, time) - ClearPrints() - BeginTextCommandPrint("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandPrint(time, 1) + ClearPrints() + BeginTextCommandPrint("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandPrint(time, 1) end function ShowLoadingPromt(msg, time, type) - CreateThread(function() - Wait(0) + CreateThread(function() + Wait(0) - BeginTextCommandBusyspinnerOn("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandBusyspinnerOn(type) - Wait(time) + BeginTextCommandBusyspinnerOn("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandBusyspinnerOn(type) + Wait(time) - BusyspinnerOff() - end) + BusyspinnerOff() + end) end function OpenCloakroom() - local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, - { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, - { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "wear_citizen" then - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - end) - elseif element.value == "wear_work" 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 - ESX.CloseContext() - end, function() - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, + { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, + { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "wear_citizen" then + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + elseif element.value == "wear_work" 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 + ESX.CloseContext() + end, function() + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end) end function OpenVehicleSpawnerMenu() - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, - } - - if Config.EnableSocietyOwnedVehicles then - ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) - if #vehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #vehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", - value = vehicles[i], - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - local vehicleProps = element.value - ESX.TriggerServerCallback("bpt_importjob:SpawnVehicle", function() - return - end, vehicleProps.model, vehicleProps) - TriggerServerEvent("esx_society:removeVehicleFromGarage", "import", vehicleProps) - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end, "import") - else -- not society vehicles - if #Config.AuthorizedVehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #Config.AuthorizedVehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = Config.AuthorizedVehicles[i].label, - value = Config.AuthorizedVehicles[i].model, - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - ESX.TriggerServerCallback("bpt_importjob:SpawnVehicle", function() - ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") - end, element.value, { plate = "IMPO JOB" }) - ESX.CloseContext() - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, + } + + if Config.EnableSocietyOwnedVehicles then + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) + if #vehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #vehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + local vehicleProps = element.value + ESX.TriggerServerCallback("bpt_importjob:SpawnVehicle", function() + return + end, vehicleProps.model, vehicleProps) + TriggerServerEvent("esx_society:removeVehicleFromGarage", "import", vehicleProps) + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end, "import") + else -- not society vehicles + if #Config.AuthorizedVehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #Config.AuthorizedVehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = Config.AuthorizedVehicles[i].label, + value = Config.AuthorizedVehicles[i].model, + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + ESX.TriggerServerCallback("bpt_importjob:SpawnVehicle", function() + ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") + end, element.value, { plate = "IMPO JOB" }) + ESX.CloseContext() + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end end function DeleteJobVehicle() - if Config.EnableSocietyOwnedVehicles then - local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent("esx_society:putVehicleInGarage", "import", vehicleProps) - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - else - if IsInAuthorizedVehicle() then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - - if Config.MaxInService ~= -1 then - TriggerServerEvent("esx_service:disableService", "import") - end - else - ESX.ShowNotification(TranslateCap("only_import")) - end - end + if Config.EnableSocietyOwnedVehicles then + local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) + TriggerServerEvent("esx_society:putVehicleInGarage", "import", vehicleProps) + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + else + if IsInAuthorizedVehicle() then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + + if Config.MaxInService ~= -1 then + TriggerServerEvent("esx_service:disableService", "import") + end + else + ESX.ShowNotification(TranslateCap("only_import")) + end + end end function OpenImportActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-import", title = TranslateCap("import") }, - { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, - { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then - elements[#elements + 1] = { - icon = "fas fa-wallet", - title = TranslateCap("boss_actions"), - value = "boss_actions", - } - end - - ESX.OpenContext("right", elements, function(_, element) - if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then - exports.ox_inventory:openInventory("stash", "society_import") - return ESX.CloseContext() - elseif element.value == "put_stock" then - OpenPutStocksMenu() - elseif element.value == "get_stock" then - OpenGetStocksMenu() - elseif element.value == "boss_actions" then - TriggerEvent("esx_society:openBossMenu", "import", function(_, menu) - menu.close() - end) - end - end, function() - CurrentAction = "import_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-import", title = TranslateCap("import") }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then + elements[#elements + 1] = { + icon = "fas fa-wallet", + title = TranslateCap("boss_actions"), + value = "boss_actions", + } + end + + ESX.OpenContext("right", elements, function(_, element) + if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_import") + return ESX.CloseContext() + elseif element.value == "put_stock" then + OpenPutStocksMenu() + elseif element.value == "get_stock" then + OpenGetStocksMenu() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "import", function(_, menu) + menu.close() + end) + end + end, function() + CurrentAction = "import_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + end) end function OpenMobileImportActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-import", title = TranslateCap("import") }, - { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "billing" then - local elements2 = { - { unselectable = true, icon = "fas fa-import", title = element.title }, - { - title = TranslateCap("amount"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 250000, - inputPlaceholder = TranslateCap("bill_amount"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2) - local amount = tonumber(menu2.eles[2].inputValue) - if amount == nil then - ESX.ShowNotification(TranslateCap("amount_invalid")) - else - ESX.CloseContext() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap("no_players_near")) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(closestPlayer), - "society_import", - "Import", - amount - ) - ESX.ShowNotification(TranslateCap("billing_sent")) - end - end - end) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-import", title = TranslateCap("import") }, + { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "billing" then + local elements2 = { + { unselectable = true, icon = "fas fa-import", title = element.title }, + { + title = TranslateCap("amount"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 250000, + inputPlaceholder = TranslateCap("bill_amount"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2) + local amount = tonumber(menu2.eles[2].inputValue) + if amount == nil then + ESX.ShowNotification(TranslateCap("amount_invalid")) + else + ESX.CloseContext() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players_near")) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_import", "Import", amount) + ESX.ShowNotification(TranslateCap("billing_sent")) + end + end + end) + end + end) end function IsInAuthorizedVehicle() - local playerPed = PlayerPedId() - local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) + local playerPed = PlayerPedId() + local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) - for i = 1, #Config.AuthorizedVehicles, 1 do - if vehModel == joaat(Config.AuthorizedVehicles[i].model) then - return true - end - end + for i = 1, #Config.AuthorizedVehicles, 1 do + if vehModel == joaat(Config.AuthorizedVehicles[i].model) then + return true + end + end - return false + return false end AddEventHandler("bpt_importjob:hasEnteredMarker", function(zone) - if zone == "VehicleSpawner" then - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - elseif zone == "VehicleDeleter" then - local playerPed = PlayerPedId() - local vehicle = GetVehiclePedIsIn(playerPed, false) - - if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then - CurrentAction = "delete_vehicle" - CurrentActionMsg = TranslateCap("store_veh") - CurrentActionData = { - vehicle = vehicle, - } - end - elseif zone == "ImportActions" then - CurrentAction = "import_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - elseif zone == "Cloakroom" then - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end + if zone == "VehicleSpawner" then + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + elseif zone == "VehicleDeleter" then + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("store_veh") + CurrentActionData = { + vehicle = vehicle, + } + end + elseif zone == "ImportActions" then + CurrentAction = "import_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + elseif zone == "Cloakroom" then + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end end) AddEventHandler("bpt_importjob:hasExitedMarker", function() - ESX.CloseContext() - CurrentAction = nil + ESX.CloseContext() + CurrentAction = nil end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord( - Config.Zones.ImportActions.Pos.x, - Config.Zones.ImportActions.Pos.y, - Config.Zones.ImportActions.Pos.z - ) - - SetBlipSprite(blip, 478) - SetBlipDisplay(blip, 4) - SetBlipScale(blip, 1.0) - SetBlipColour(blip, 21) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("blip_import")) - EndTextCommandSetBlipName(blip) + local blip = AddBlipForCoord(Config.Zones.ImportActions.Pos.x, Config.Zones.ImportActions.Pos.y, Config.Zones.ImportActions.Pos.z) + + SetBlipSprite(blip, 478) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 21) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("blip_import")) + EndTextCommandSetBlipName(blip) end) -- Enter / Exit marker events, and draw markers CreateThread(function() - while true do - local sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == "import" then - local coords = GetEntityCoords(PlayerPedId()) - local isInMarker, currentZone = false - local inVeh = IsPedInAnyVehicle(PlayerPedId()) - - for k, v in pairs(Config.Zones) do - local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) - local distance = #(coords - zonePos) - - if v.Type ~= -1 and distance < Config.DrawDistance then - sleep = 0 - if k == "VehicleDeleter" then - if inVeh then - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - else - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - end - - if distance < v.Size.x then - isInMarker, currentZone = true, k - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker, LastZone = true, currentZone - TriggerEvent("bpt_importjob:hasEnteredMarker", currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent("bpt_importjob:hasExitedMarker", LastZone) - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if ESX.PlayerData.job and ESX.PlayerData.job.name == "import" then + local coords = GetEntityCoords(PlayerPedId()) + local isInMarker, currentZone = false + local inVeh = IsPedInAnyVehicle(PlayerPedId()) + + for k, v in pairs(Config.Zones) do + local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) + local distance = #(coords - zonePos) + + if v.Type ~= -1 and distance < Config.DrawDistance then + sleep = 0 + if k == "VehicleDeleter" then + if inVeh then + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + else + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + end + + if distance < v.Size.x then + isInMarker, currentZone = true, k + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker, LastZone = true, currentZone + TriggerEvent("bpt_importjob:hasEnteredMarker", currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("bpt_importjob:hasExitedMarker", LastZone) + end + end + Wait(sleep) + end end) -- Key Controls CreateThread(function() - while true do - local sleep = 1500 - if CurrentAction and not ESX.PlayerData.dead then - sleep = 0 - ESX.ShowHelpNotification(CurrentActionMsg) - - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "import" then - if CurrentAction == "import_actions_menu" then - OpenImportActionsMenu() - elseif CurrentAction == "cloakroom" then - OpenCloakroom() - elseif CurrentAction == "vehicle_spawner" then - OpenVehicleSpawnerMenu() - elseif CurrentAction == "delete_vehicle" then - DeleteJobVehicle() - end - - CurrentAction = nil - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if CurrentAction and not ESX.PlayerData.dead then + sleep = 0 + ESX.ShowHelpNotification(CurrentActionMsg) + + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "import" then + if CurrentAction == "import_actions_menu" then + OpenImportActionsMenu() + elseif CurrentAction == "cloakroom" then + OpenCloakroom() + elseif CurrentAction == "vehicle_spawner" then + OpenVehicleSpawnerMenu() + elseif CurrentAction == "delete_vehicle" then + DeleteJobVehicle() + end + + CurrentAction = nil + end + end + Wait(sleep) + end end) RegisterCommand("importmenu", function() - if - not ESX.PlayerData.dead - and Config.EnablePlayerManagement - and ESX.PlayerData.job - and ESX.PlayerData.job.name == "import" - then - OpenMobileImportActionsMenu() - end + if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == "import" then + OpenMobileImportActionsMenu() + end end, false) RegisterKeyMapping("importmenu", "Open Import Menu", "keyboard", "f6") diff --git a/server-data/resources/[bpt_addons]/bpt_taxijob/client/main.lua b/server-data/resources/[bpt_addons]/bpt_taxijob/client/main.lua index 61bd59d32..92a8a019a 100644 --- a/server-data/resources/[bpt_addons]/bpt_taxijob/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_taxijob/client/main.lua @@ -1,27 +1,26 @@ -local HasAlreadyEnteredMarker, OnJob, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, -CurrentActionData = false, false, false, false, false, {} +local HasAlreadyEnteredMarker, OnJob, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, CurrentActionData = false, false, false, false, false, {} local CurrentCustomer, CurrentCustomerBlip, DestinationBlip, targetCoords, LastZone, CurrentAction, CurrentActionMsg -RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(xPlayer) +RegisterNetEvent("esx:playerLoaded") +AddEventHandler("esx:playerLoaded", function(xPlayer) ESX.PlayerData = xPlayer ESX.PlayerLoaded = true end) -RegisterNetEvent('esx:onPlayerLogout') -AddEventHandler('esx:onPlayerLogout', function() +RegisterNetEvent("esx:onPlayerLogout") +AddEventHandler("esx:onPlayerLogout", function() ESX.PlayerLoaded = false ESX.PlayerData = {} end) -RegisterNetEvent('esx:setJob') -AddEventHandler('esx:setJob', function(job) +RegisterNetEvent("esx:setJob") +AddEventHandler("esx:setJob", function(job) ESX.PlayerData.job = job end) function DrawSub(msg, time) ClearPrints() - BeginTextCommandPrint('STRING') + BeginTextCommandPrint("STRING") AddTextComponentSubstringPlayerName(msg) EndTextCommandPrint(time, 1) end @@ -30,7 +29,7 @@ function ShowLoadingPromt(msg, time, type) CreateThread(function() Wait(0) - BeginTextCommandBusyspinnerOn('STRING') + BeginTextCommandBusyspinnerOn("STRING") AddTextComponentSubstringPlayerName(msg) EndTextCommandBusyspinnerOn(type) Wait(time) @@ -73,7 +72,7 @@ function ClearCurrentMission() end function StartTaxiJob() - ShowLoadingPromt(TranslateCap('taking_service'), 5000, 3) + ShowLoadingPromt(TranslateCap("taking_service"), 5000, 3) ClearCurrentMission() OnJob = true @@ -93,55 +92,55 @@ function StopTaxiJob() ClearCurrentMission() OnJob = false - DrawSub(TranslateCap('mission_complete'), 5000) + DrawSub(TranslateCap("mission_complete"), 5000) end function OpenCloakroom() local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap('cloakroom_menu') }, - { icon = "fas fa-shirt", title = TranslateCap('wear_citizen'), value = "wear_citizen" }, - { icon = "fas fa-shirt", title = TranslateCap('wear_work'), value = "wear_work" }, + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, + { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, + { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, } ESX.OpenContext("right", elements, function(menu, element) if element.value == "wear_citizen" then - ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) - TriggerEvent('skinchanger:loadSkin', skin) + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) end) elseif element.value == "wear_work" then - ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) if skin.sex == 0 then - TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male) + TriggerEvent("skinchanger:loadClothes", skin, jobSkin.skin_male) else - TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female) + TriggerEvent("skinchanger:loadClothes", skin, jobSkin.skin_female) end end) end end, function(menu) - CurrentAction = 'cloakroom' - CurrentActionMsg = TranslateCap('cloakroom_prompt') + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") CurrentActionData = {} end) end function OpenVehicleSpawnerMenu() local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap('spawn_veh') } + { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, } if Config.EnableSocietyOwnedVehicles then - ESX.TriggerServerCallback('esx_society:getVehiclesInGarage', function(vehicles) + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) for i = 1, #vehicles, 1 do elements[#elements + 1] = { icon = "fas fa-car", - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. ' [' .. vehicles[i].plate .. ']', - value = vehicles[i] + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], } end ESX.OpenContext("right", elements, function(menu, element) if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap('spawnpoint_blocked')) + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) return end @@ -149,35 +148,35 @@ function OpenVehicleSpawnerMenu() ESX.TriggerServerCallback("bpt_taxijob:SpawnVehicle", function() return end, vehicleProps.model, vehicleProps) - TriggerServerEvent('esx_society:removeVehicleFromGarage', 'taxi', vehicleProps) + TriggerServerEvent("esx_society:removeVehicleFromGarage", "taxi", vehicleProps) ESX.CloseContext() end, function(menu) - CurrentAction = 'vehicle_spawner' - CurrentActionMsg = TranslateCap('spawner_prompt') + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") CurrentActionData = {} end) - end, 'taxi') + end, "taxi") else -- not society vehicles if #Config.AuthorizedVehicles == 0 then - ESX.ShowNotification(TranslateCap('empty_authorized_vehicles_table'), "error") + ESX.ShowNotification(TranslateCap("empty_authorized_vehicles_table"), "error") return end ESX.OpenContext("right", Config.AuthorizedVehicles, function(menu, element) if not element.model or string.len(element.model) == 0 then - ESX.ShowNotification(TranslateCap('unknow_model'), "error") + ESX.ShowNotification(TranslateCap("unknow_model"), "error") return end if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap('spawnpoint_blocked')) + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) return end ESX.TriggerServerCallback("bpt_taxijob:SpawnVehicle", function() - ESX.ShowNotification(TranslateCap('vehicle_spawned', element.title), "success") + ESX.ShowNotification(TranslateCap("vehicle_spawned", element.title), "success") end, element.model, { plate = "TAXI JOB" }) ESX.CloseContext() end, function(menu) - CurrentAction = 'vehicle_spawner' - CurrentActionMsg = TranslateCap('spawner_prompt') + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") CurrentActionData = {} end) end @@ -188,84 +187,83 @@ function DeleteJobVehicle() if Config.EnableSocietyOwnedVehicles then local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent('esx_society:putVehicleInGarage', 'taxi', vehicleProps) + TriggerServerEvent("esx_society:putVehicleInGarage", "taxi", vehicleProps) ESX.Game.DeleteVehicle(CurrentActionData.vehicle) else if IsInAuthorizedVehicle() then ESX.Game.DeleteVehicle(CurrentActionData.vehicle) if Config.MaxInService ~= -1 then - TriggerServerEvent('esx_service:disableService', 'taxi') + TriggerServerEvent("esx_service:disableService", "taxi") end else - ESX.ShowNotification(TranslateCap('only_taxi')) + ESX.ShowNotification(TranslateCap("only_taxi")) end end end function OpenTaxiActionsMenu() local elements = { - { unselectable = true, icon = "fas fa-taxi", title = TranslateCap('taxi') }, - { icon = "fas fa-box", title = TranslateCap('deposit_stock'), value = 'put_stock' }, - { icon = "fas fa-box", title = TranslateCap('take_stock'), value = 'get_stock' } + { unselectable = true, icon = "fas fa-taxi", title = TranslateCap("taxi") }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, } - if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == 'boss' then + if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then elements[#elements + 1] = { icon = "fas fa-wallet", - title = TranslateCap('boss_actions'), - value = "boss_actions" + title = TranslateCap("boss_actions"), + value = "boss_actions", } end ESX.OpenContext("right", elements, function(menu, element) - if Config.OxInventory and (element.value == 'put_stock' or element.value == 'get_stock') then - exports.ox_inventory:openInventory('stash', 'society_taxi') + if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_taxi") return ESX.CloseContext() - elseif element.value == 'put_stock' then + elseif element.value == "put_stock" then OpenPutStocksMenu() - elseif element.value == 'get_stock' then + elseif element.value == "get_stock" then OpenGetStocksMenu() - elseif element.value == 'boss_actions' then - TriggerEvent('esx_society:openBossMenu', 'taxi', function() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "taxi", function() menu.close() end) end end, function(menu) - CurrentAction = 'taxi_actions_menu' - CurrentActionMsg = TranslateCap('press_to_open') + CurrentAction = "taxi_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") CurrentActionData = {} end) end function OpenMobileTaxiActionsMenu() local elements = { - { unselectable = true, icon = "fas fa-taxi", title = TranslateCap('taxi') }, - { icon = "fas fa-scroll", title = TranslateCap('billing'), value = "billing" }, - { icon = "fas fa-taxi", title = TranslateCap('start_job'), value = "start_job" }, + { unselectable = true, icon = "fas fa-taxi", title = TranslateCap("taxi") }, + { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, + { icon = "fas fa-taxi", title = TranslateCap("start_job"), value = "start_job" }, } ESX.OpenContext("right", elements, function(menu, element) if element.value == "billing" then local elements2 = { - { unselectable = true, icon = "fas fa-taxi", title = element.title }, - { title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = TranslateCap('bill_amount') }, - { icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm" } + { unselectable = true, icon = "fas fa-taxi", title = element.title }, + { title = TranslateCap("amount"), input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = TranslateCap("bill_amount") }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, } ESX.OpenContext("right", elements2, function(menu2, element2) local amount = tonumber(menu2.eles[2].inputValue) if amount == nil then - ESX.ShowNotification(TranslateCap('amount_invalid')) + ESX.ShowNotification(TranslateCap("amount_invalid")) else ESX.CloseContext() local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap('no_players_near')) + ESX.ShowNotification(TranslateCap("no_players_near")) else - TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_taxi', - 'Taxi', amount) - ESX.ShowNotification(TranslateCap('billing_sent')) + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_taxi", "Taxi", amount) + ESX.ShowNotification(TranslateCap("billing_sent")) end end end) @@ -274,7 +272,7 @@ function OpenMobileTaxiActionsMenu() ESX.CloseContext() StopTaxiJob() else - if ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'taxi' then + if ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == "taxi" then local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) @@ -287,14 +285,14 @@ function OpenMobileTaxiActionsMenu() ESX.CloseContext() StartTaxiJob() else - ESX.ShowNotification(TranslateCap('must_in_taxi')) + ESX.ShowNotification(TranslateCap("must_in_taxi")) end end else if tonumber(ESX.PlayerData.job.grade) >= 3 then - ESX.ShowNotification(TranslateCap('must_in_vehicle')) + ESX.ShowNotification(TranslateCap("must_in_vehicle")) else - ESX.ShowNotification(TranslateCap('must_in_taxi')) + ESX.ShowNotification(TranslateCap("must_in_taxi")) end end end @@ -317,35 +315,35 @@ function IsInAuthorizedVehicle() end function OpenGetStocksMenu() - ESX.TriggerServerCallback('bpt_taxijob:getStockItems', function(items) + ESX.TriggerServerCallback("bpt_taxijob:getStockItems", function(items) local elements = { - { unselectable = true, icon = "fas fa-box", title = TranslateCap('taxi_stock') } + { unselectable = true, icon = "fas fa-box", title = TranslateCap("taxi_stock") }, } for i = 1, #items, 1 do elements[#elements + 1] = { icon = "fas fa-box", - title = 'x' .. items[i].count .. ' ' .. items[i].label, - value = items[i].name + title = "x" .. items[i].count .. " " .. items[i].label, + value = items[i].name, } end ESX.OpenContext("right", elements, function(menu, element) local itemName = element.value local elements2 = { - { unselectable = true, icon = "fas fa-box", title = element.title }, - { title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap('withdraw_amount') }, - { icon = "fas fa-check-double", title = TranslateCap('confirm'), value = "confirm" } + { unselectable = true, icon = "fas fa-box", title = element.title }, + { title = TranslateCap("amount"), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap("withdraw_amount") }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, } ESX.OpenContext("right", elements2, function(menu2, element2) local count = tonumber(menu2.eles[2].inputValue) if count == nil then - ESX.ShowNotification(TranslateCap('quantity_invalid')) + ESX.ShowNotification(TranslateCap("quantity_invalid")) else ESX.CloseContext() - TriggerServerEvent('bpt_taxijob:getStockItem', itemName, count) + TriggerServerEvent("bpt_taxijob:getStockItem", itemName, count) Wait(1000) OpenGetStocksMenu() @@ -353,16 +351,16 @@ function OpenGetStocksMenu() end) end) end, function(menu) - CurrentAction = 'taxi_actions_menu' - CurrentActionMsg = TranslateCap('press_to_open') + CurrentAction = "taxi_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") CurrentActionData = {} end) end function OpenPutStocksMenu() - ESX.TriggerServerCallback('bpt_taxijob:getPlayerInventory', function(inventory) + ESX.TriggerServerCallback("bpt_taxijob:getPlayerInventory", function(inventory) local elements = { - { unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory') } + { unselectable = true, icon = "fas fa-box", title = TranslateCap("inventory") }, } for i = 1, #inventory.items, 1 do @@ -370,9 +368,9 @@ function OpenPutStocksMenu() if item.count > 0 then elements[#elements + 1] = { icon = "fas fa-box", - title = item.label .. ' x' .. item.count, - type = 'item_standard', - value = item.name + title = item.label .. " x" .. item.count, + type = "item_standard", + value = item.name, } end end @@ -381,80 +379,78 @@ function OpenPutStocksMenu() local itemName = element.value local elements2 = { - { unselectable = true, icon = "fas fa-box", title = element.title }, - { title = TranslateCap('amount'), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap('deposit_amount') }, - { icon = "fas fa-check-double", title = "Confirm", value = "confirm" } + { unselectable = true, icon = "fas fa-box", title = element.title }, + { title = TranslateCap("amount"), input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = TranslateCap("deposit_amount") }, + { icon = "fas fa-check-double", title = "Confirm", value = "confirm" }, } ESX.OpenContext("right", elements2, function(menu2, element2) local count = tonumber(menu2.eles[2].inputValue) if count == nil then - ESX.ShowNotification(TranslateCap('quantity_invalid')) + ESX.ShowNotification(TranslateCap("quantity_invalid")) else ESX.CloseContext() -- todo: refresh on callback - TriggerServerEvent('bpt_taxijob:putStockItems', itemName, count) + TriggerServerEvent("bpt_taxijob:putStockItems", itemName, count) Wait(1000) OpenPutStocksMenu() end end) end) end, function(menu) - CurrentAction = 'taxi_actions_menu' - CurrentActionMsg = TranslateCap('press_to_open') + CurrentAction = "taxi_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") CurrentActionData = {} end) end -AddEventHandler('bpt_taxijob:hasEnteredMarker', function(zone) - if zone == 'VehicleSpawner' then - CurrentAction = 'vehicle_spawner' - CurrentActionMsg = TranslateCap('spawner_prompt') +AddEventHandler("bpt_taxijob:hasEnteredMarker", function(zone) + if zone == "VehicleSpawner" then + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") CurrentActionData = {} - elseif zone == 'VehicleDeleter' then + elseif zone == "VehicleDeleter" then local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then - CurrentAction = 'delete_vehicle' - CurrentActionMsg = TranslateCap('store_veh') + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("store_veh") CurrentActionData = { - vehicle = vehicle + vehicle = vehicle, } end - elseif zone == 'TaxiActions' then - CurrentAction = 'taxi_actions_menu' - CurrentActionMsg = TranslateCap('press_to_open') + elseif zone == "TaxiActions" then + CurrentAction = "taxi_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") CurrentActionData = {} - elseif zone == 'Cloakroom' then - CurrentAction = 'cloakroom' - CurrentActionMsg = TranslateCap('cloakroom_prompt') + elseif zone == "Cloakroom" then + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") CurrentActionData = {} end end) -AddEventHandler('bpt_taxijob:hasExitedMarker', function(zone) +AddEventHandler("bpt_taxijob:hasExitedMarker", function(zone) ESX.CloseContext() CurrentAction = nil end) -RegisterNetEvent('esx_phone:loaded') -AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts) +RegisterNetEvent("esx_phone:loaded") +AddEventHandler("esx_phone:loaded", function(phoneNumber, contacts) local specialContact = { - name = TranslateCap('phone_taxi'), - number = 'taxi', - base64Icon = - 'data:image/png;base64,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' + name = TranslateCap("phone_taxi"), + number = "taxi", + base64Icon = "data:image/png;base64,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", } - TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon) + TriggerEvent("esx_phone:addSpecialContact", specialContact.name, specialContact.number, specialContact.base64Icon) end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord(Config.Zones.TaxiActions.Pos.x, Config.Zones.TaxiActions.Pos.y, - Config.Zones.TaxiActions.Pos.z) + local blip = AddBlipForCoord(Config.Zones.TaxiActions.Pos.x, Config.Zones.TaxiActions.Pos.y, Config.Zones.TaxiActions.Pos.z) SetBlipSprite(blip, 198) SetBlipDisplay(blip, 4) @@ -462,8 +458,8 @@ CreateThread(function() SetBlipColour(blip, 5) SetBlipAsShortRange(blip, true) - BeginTextCommandSetBlipName('STRING') - AddTextComponentSubstringPlayerName(TranslateCap('blip_taxi')) + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("blip_taxi")) EndTextCommandSetBlipName(blip) end) @@ -471,7 +467,7 @@ end) CreateThread(function() while true do local sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'taxi' then + if ESX.PlayerData.job and ESX.PlayerData.job.name == "taxi" then local coords = GetEntityCoords(PlayerPedId()) local isInMarker, currentZone = false @@ -481,8 +477,7 @@ CreateThread(function() if v.Type ~= -1 and distance < Config.DrawDistance then sleep = 0 - DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, - v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) end if distance < v.Size.x then @@ -492,12 +487,12 @@ CreateThread(function() if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then HasAlreadyEnteredMarker, LastZone = true, currentZone - TriggerEvent('bpt_taxijob:hasEnteredMarker', currentZone) + TriggerEvent("bpt_taxijob:hasEnteredMarker", currentZone) end if not isInMarker and HasAlreadyEnteredMarker then HasAlreadyEnteredMarker = false - TriggerEvent('bpt_taxijob:hasExitedMarker', LastZone) + TriggerEvent("bpt_taxijob:hasExitedMarker", LastZone) end end Wait(sleep) @@ -513,7 +508,7 @@ CreateThread(function() Sleep = 0 local playerPed = PlayerPedId() if CurrentCustomer == nil then - DrawSub(TranslateCap('drive_search_pass'), 5000) + DrawSub(TranslateCap("drive_search_pass"), 5000) if IsPedInAnyVehicle(playerPed, false) and OnJob then Wait(5000) @@ -534,12 +529,12 @@ CreateThread(function() local standTime = GetRandomIntInRange(60000, 180000) TaskStandStill(CurrentCustomer, standTime) - ESX.ShowNotification(TranslateCap('customer_found')) + ESX.ShowNotification(TranslateCap("customer_found")) end end else if IsPedFatallyInjured(CurrentCustomer) then - ESX.ShowNotification(TranslateCap('client_unconcious')) + ESX.ShowNotification(TranslateCap("client_unconcious")) if DoesBlipExist(CurrentCustomerBlip) then RemoveBlip(CurrentCustomerBlip) @@ -551,8 +546,7 @@ CreateThread(function() SetEntityAsMissionEntity(CurrentCustomer, false, true) - CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = - nil, nil, nil, false, false, false, nil + CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = nil, nil, nil, false, false, false, nil end if IsPedInAnyVehicle(playerPed, false) then @@ -568,12 +562,11 @@ CreateThread(function() if targetDistance <= 10.0 then TaskLeaveVehicle(CurrentCustomer, vehicle, 0) - ESX.ShowNotification(TranslateCap('arrive_dest')) + ESX.ShowNotification(TranslateCap("arrive_dest")) - TaskGoStraightToCoord(CurrentCustomer, targetCoords.x, targetCoords.y, targetCoords.z, - 1.0, -1, 0.0, 0.0) + TaskGoStraightToCoord(CurrentCustomer, targetCoords.x, targetCoords.y, targetCoords.z, 1.0, -1, 0.0, 0.0) SetEntityAsMissionEntity(CurrentCustomer, false, true) - TriggerServerEvent('bpt_taxijob:success') + TriggerServerEvent("bpt_taxijob:success") RemoveBlip(DestinationBlip) local function scope(customer) @@ -584,13 +577,11 @@ CreateThread(function() scope(CurrentCustomer) - CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = - nil, nil, nil, false, false, false, nil + CurrentCustomer, CurrentCustomerBlip, DestinationBlip, IsNearCustomer, CustomerIsEnteringVehicle, CustomerEnteredVehicle, targetCoords = nil, nil, nil, false, false, false, nil end if targetCoords then - DrawMarker(36, targetCoords.x, targetCoords.y, targetCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) + DrawMarker(36, targetCoords.x, targetCoords.y, targetCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) end else RemoveBlip(CurrentCustomerBlip) @@ -604,36 +595,33 @@ CreateThread(function() distance = #(playerCoords - targetCoords) end - local street = table.pack(GetStreetNameAtCoord(targetCoords.x, targetCoords.y, - targetCoords.z)) + local street = table.pack(GetStreetNameAtCoord(targetCoords.x, targetCoords.y, targetCoords.z)) local msg = nil if street[2] ~= 0 and street[2] ~= nil then - msg = string.format(TranslateCap('take_me_to_near', GetStreetNameFromHashKey(street[1]), - GetStreetNameFromHashKey(street[2]))) + msg = string.format(TranslateCap("take_me_to_near", GetStreetNameFromHashKey(street[1]), GetStreetNameFromHashKey(street[2]))) else - msg = string.format(TranslateCap('take_me_to', GetStreetNameFromHashKey(street[1]))) + msg = string.format(TranslateCap("take_me_to", GetStreetNameFromHashKey(street[1]))) end ESX.ShowNotification(msg) DestinationBlip = AddBlipForCoord(targetCoords.x, targetCoords.y, targetCoords.z) - BeginTextCommandSetBlipName('STRING') - AddTextComponentSubstringPlayerName('Destination') + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName("Destination") EndTextCommandSetBlipName(DestinationBlip) SetBlipRoute(DestinationBlip, true) CustomerEnteredVehicle = true end else - DrawMarker(36, customerCoords.x, customerCoords.y, customerCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) + DrawMarker(36, customerCoords.x, customerCoords.y, customerCoords.z + 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 234, 223, 72, 155, false, false, 2, true, nil, nil, false) if not CustomerEnteredVehicle then if customerDistance <= 40.0 then if not IsNearCustomer then - ESX.ShowNotification(TranslateCap('close_to_client')) + ESX.ShowNotification(TranslateCap("close_to_client")) IsNearCustomer = true end end @@ -660,7 +648,7 @@ CreateThread(function() end end else - DrawSub(TranslateCap('return_to_veh'), 5000) + DrawSub(TranslateCap("return_to_veh"), 5000) end end end @@ -675,7 +663,7 @@ CreateThread(function() if not IsInAuthorizedVehicle() then ClearCurrentMission() OnJob = false - ESX.ShowNotification(TranslateCap('not_in_taxi')) + ESX.ShowNotification(TranslateCap("not_in_taxi")) end end end @@ -689,14 +677,14 @@ CreateThread(function() sleep = 0 ESX.ShowHelpNotification(CurrentActionMsg) - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == 'taxi' then - if CurrentAction == 'taxi_actions_menu' then + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "taxi" then + if CurrentAction == "taxi_actions_menu" then OpenTaxiActionsMenu() - elseif CurrentAction == 'cloakroom' then + elseif CurrentAction == "cloakroom" then OpenCloakroom() - elseif CurrentAction == 'vehicle_spawner' then + elseif CurrentAction == "vehicle_spawner" then OpenVehicleSpawnerMenu() - elseif CurrentAction == 'delete_vehicle' then + elseif CurrentAction == "delete_vehicle" then DeleteJobVehicle() end @@ -707,11 +695,10 @@ CreateThread(function() end end) -RegisterCommand('taximenu', function() - if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == - 'taxi' then +RegisterCommand("taximenu", function() + if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == "taxi" then OpenMobileTaxiActionsMenu() end end, false) -RegisterKeyMapping('taximenu', 'Open Taxi Menu', 'keyboard', 'f6') +RegisterKeyMapping("taximenu", "Open Taxi Menu", "keyboard", "f6") diff --git a/server-data/resources/[bpt_addons]/bpt_unicornjob/client/main.lua b/server-data/resources/[bpt_addons]/bpt_unicornjob/client/main.lua index 43ed87d72..42a35d08a 100644 --- a/server-data/resources/[bpt_addons]/bpt_unicornjob/client/main.lua +++ b/server-data/resources/[bpt_addons]/bpt_unicornjob/client/main.lua @@ -4,440 +4,375 @@ local LastZone RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(xPlayer) - ESX.PlayerData = xPlayer - ESX.PlayerLoaded = true + ESX.PlayerData = xPlayer + ESX.PlayerLoaded = true end) RegisterNetEvent("esx:onPlayerLogout") AddEventHandler("esx:onPlayerLogout", function() - ESX.PlayerLoaded = false - ESX.PlayerData = {} + ESX.PlayerLoaded = false + ESX.PlayerData = {} end) RegisterNetEvent("esx:setJob") AddEventHandler("esx:setJob", function(job) - ESX.PlayerData.job = job + ESX.PlayerData.job = job end) function DrawSub(msg, time) - ClearPrints() - BeginTextCommandPrint("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandPrint(time, 1) + ClearPrints() + BeginTextCommandPrint("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandPrint(time, 1) end function ShowLoadingPromt(msg, time, type) - CreateThread(function() - Wait(0) + CreateThread(function() + Wait(0) - BeginTextCommandBusyspinnerOn("STRING") - AddTextComponentSubstringPlayerName(msg) - EndTextCommandBusyspinnerOn(type) - Wait(time) + BeginTextCommandBusyspinnerOn("STRING") + AddTextComponentSubstringPlayerName(msg) + EndTextCommandBusyspinnerOn(type) + Wait(time) - BusyspinnerOff() - end) + BusyspinnerOff() + end) end function OpenCloakroom() - local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, - { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, - { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "wear_citizen" then - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - end) - elseif element.value == "wear_work" 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 - ESX.CloseContext() - end, function() - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom_menu") }, + { icon = "fas fa-shirt", title = TranslateCap("wear_citizen"), value = "wear_citizen" }, + { icon = "fas fa-shirt", title = TranslateCap("wear_work"), value = "wear_work" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "wear_citizen" then + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + elseif element.value == "wear_work" 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 + ESX.CloseContext() + end, function() + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end) end function OpenVehicleSpawnerMenu() - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, - } - - if Config.EnableSocietyOwnedVehicles then - ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) - if #vehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #vehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", - value = vehicles[i], - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - local vehicleProps = element.value - ESX.TriggerServerCallback("bpt_unicornjob:SpawnVehicle", function() - return - end, vehicleProps.model, vehicleProps) - TriggerServerEvent("esx_society:removeVehicleFromGarage", "unicorn", vehicleProps) - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end, "unicorn") - else -- not society vehicles - if #Config.AuthorizedVehicles == 0 then - ESX.ShowNotification(TranslateCap("empty_garage")) - return - end - - for i = 1, #Config.AuthorizedVehicles, 1 do - elements[#elements + 1] = { - icon = "fas fa-car", - title = Config.AuthorizedVehicles[i].label, - value = Config.AuthorizedVehicles[i].model, - } - end - - ESX.OpenContext("right", elements, function(_, element) - if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then - ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) - return - end - - if element.value == nil then - print("ERROR: Context menu clicked item value is nil!") - return - end - - ESX.TriggerServerCallback("bpt_unicornjob:SpawnVehicle", function() - ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") - end, element.value, { plate = "CORN JOB" }) - ESX.CloseContext() - end, function() - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - end) - end + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("spawn_veh") }, + } + + if Config.EnableSocietyOwnedVehicles then + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) + if #vehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #vehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + local vehicleProps = element.value + ESX.TriggerServerCallback("bpt_unicornjob:SpawnVehicle", function() + return + end, vehicleProps.model, vehicleProps) + TriggerServerEvent("esx_society:removeVehicleFromGarage", "unicorn", vehicleProps) + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end, "unicorn") + else -- not society vehicles + if #Config.AuthorizedVehicles == 0 then + ESX.ShowNotification(TranslateCap("empty_garage")) + return + end + + for i = 1, #Config.AuthorizedVehicles, 1 do + elements[#elements + 1] = { + icon = "fas fa-car", + title = Config.AuthorizedVehicles[i].label, + value = Config.AuthorizedVehicles[i].model, + } + end + + ESX.OpenContext("right", elements, function(_, element) + if not ESX.Game.IsSpawnPointClear(Config.Zones.VehicleSpawnPoint.Pos, 5.0) then + ESX.ShowNotification(TranslateCap("spawnpoint_blocked")) + return + end + + if element.value == nil then + print("ERROR: Context menu clicked item value is nil!") + return + end + + ESX.TriggerServerCallback("bpt_unicornjob:SpawnVehicle", function() + ESX.ShowNotification(TranslateCap("vehicle_spawned"), "success") + end, element.value, { plate = "CORN JOB" }) + ESX.CloseContext() + end, function() + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + end) + end end function DeleteJobVehicle() - if Config.EnableSocietyOwnedVehicles then - local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent("esx_society:putVehicleInGarage", "unicorn", vehicleProps) - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - else - if IsInAuthorizedVehicle() then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - - if Config.MaxInService ~= -1 then - TriggerServerEvent("esx_service:disableService", "unicorn") - end - else - ESX.ShowNotification(TranslateCap("onlyTranslateCapnicorn")) - end - end + if Config.EnableSocietyOwnedVehicles then + local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) + TriggerServerEvent("esx_society:putVehicleInGarage", "unicorn", vehicleProps) + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + else + if IsInAuthorizedVehicle() then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + + if Config.MaxInService ~= -1 then + TriggerServerEvent("esx_service:disableService", "unicorn") + end + else + ESX.ShowNotification(TranslateCap("onlyTranslateCapnicorn")) + end + end end function OpenUnicornActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-unicorn", title = TranslateCap("unicorn") }, - { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, - { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then - elements[#elements + 1] = { - icon = "fas fa-wallet", - title = TranslateCap("boss_actions"), - value = "boss_actions", - } - end - - ESX.OpenContext("right", elements, function(_, element) - if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then - exports.ox_inventory:openInventory("stash", "society_unicorn") - return ESX.CloseContext() - elseif element.value == "put_stock" then - OpenPutStocksMenu() - elseif element.value == "get_stock" then - OpenGetStocksMenu() - elseif element.value == "boss_actions" then - TriggerEvent("esx_society:openBossMenu", "unicorn", function(_, menu) - menu.close() - end) - end - end, function() - CurrentAction = "unicorn_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-unicorn", title = TranslateCap("unicorn") }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("take_stock"), value = "get_stock" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.grade_name == "boss" then + elements[#elements + 1] = { + icon = "fas fa-wallet", + title = TranslateCap("boss_actions"), + value = "boss_actions", + } + end + + ESX.OpenContext("right", elements, function(_, element) + if Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_unicorn") + return ESX.CloseContext() + elseif element.value == "put_stock" then + OpenPutStocksMenu() + elseif element.value == "get_stock" then + OpenGetStocksMenu() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "unicorn", function(_, menu) + menu.close() + end) + end + end, function() + CurrentAction = "unicorn_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + end) end function OpenMobileUnicornActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-unicorn", title = TranslateCap("unicorn") }, - { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, - } - - ESX.OpenContext("right", elements, function(_, element) - if element.value == "billing" then - local elements2 = { - { unselectable = true, icon = "fas fa-unicorn", title = element.title }, - { - title = TranslateCap("amount"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 250000, - inputPlaceholder = TranslateCap("bill_amount"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2) - local amount = tonumber(menu2.eles[2].inputValue) - if amount == nil then - ESX.ShowNotification(TranslateCap("amount_invalid")) - else - ESX.CloseContext() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap("no_players_near")) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(closestPlayer), - "societyTranslateCapnicorn", - "Unicorn", - amount - ) - ESX.ShowNotification(TranslateCap("billing_sent")) - end - end - end) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-unicorn", title = TranslateCap("unicorn") }, + { icon = "fas fa-scroll", title = TranslateCap("billing"), value = "billing" }, + } + + ESX.OpenContext("right", elements, function(_, element) + if element.value == "billing" then + local elements2 = { + { unselectable = true, icon = "fas fa-unicorn", title = element.title }, + { + title = TranslateCap("amount"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 250000, + inputPlaceholder = TranslateCap("bill_amount"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2) + local amount = tonumber(menu2.eles[2].inputValue) + if amount == nil then + ESX.ShowNotification(TranslateCap("amount_invalid")) + else + ESX.CloseContext() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players_near")) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "societyTranslateCapnicorn", "Unicorn", amount) + ESX.ShowNotification(TranslateCap("billing_sent")) + end + end + end) + end + end) end function IsInAuthorizedVehicle() - local playerPed = PlayerPedId() - local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) + local playerPed = PlayerPedId() + local vehModel = GetEntityModel(GetVehiclePedIsIn(playerPed, false)) - for i = 1, #Config.AuthorizedVehicles, 1 do - if vehModel == joaat(Config.AuthorizedVehicles[i].model) then - return true - end - end + for i = 1, #Config.AuthorizedVehicles, 1 do + if vehModel == joaat(Config.AuthorizedVehicles[i].model) then + return true + end + end - return false + return false end AddEventHandler("bpt_unicornjob:hasEnteredMarker", function(zone) - if zone == "VehicleSpawner" then - CurrentAction = "vehicle_spawner" - CurrentActionMsg = TranslateCap("spawner_prompt") - CurrentActionData = {} - elseif zone == "VehicleDeleter" then - local playerPed = PlayerPedId() - local vehicle = GetVehiclePedIsIn(playerPed, false) - - if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then - CurrentAction = "delete_vehicle" - CurrentActionMsg = TranslateCap("store_veh") - CurrentActionData = { - vehicle = vehicle, - } - end - elseif zone == "UnicornActions" then - CurrentAction = "unicorn_actions_menu" - CurrentActionMsg = TranslateCap("press_to_open") - CurrentActionData = {} - elseif zone == "Cloakroom" then - CurrentAction = "cloakroom" - CurrentActionMsg = TranslateCap("cloakroom_prompt") - CurrentActionData = {} - end + if zone == "VehicleSpawner" then + CurrentAction = "vehicle_spawner" + CurrentActionMsg = TranslateCap("spawner_prompt") + CurrentActionData = {} + elseif zone == "VehicleDeleter" then + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if IsPedInAnyVehicle(playerPed, false) and GetPedInVehicleSeat(vehicle, -1) == playerPed then + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("store_veh") + CurrentActionData = { + vehicle = vehicle, + } + end + elseif zone == "UnicornActions" then + CurrentAction = "unicorn_actions_menu" + CurrentActionMsg = TranslateCap("press_to_open") + CurrentActionData = {} + elseif zone == "Cloakroom" then + CurrentAction = "cloakroom" + CurrentActionMsg = TranslateCap("cloakroom_prompt") + CurrentActionData = {} + end end) AddEventHandler("bpt_unicornjob:hasExitedMarker", function() - ESX.CloseContext() - CurrentAction = nil + ESX.CloseContext() + CurrentAction = nil end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord( - Config.Zones.UnicornActions.Pos.x, - Config.Zones.UnicornActions.Pos.y, - Config.Zones.UnicornActions.Pos.z - ) - - SetBlipSprite(blip, 121) - SetBlipDisplay(blip, 4) - SetBlipScale(blip, 1.0) - SetBlipColour(blip, 27) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("blipTranslateCapnicorn")) - EndTextCommandSetBlipName(blip) + local blip = AddBlipForCoord(Config.Zones.UnicornActions.Pos.x, Config.Zones.UnicornActions.Pos.y, Config.Zones.UnicornActions.Pos.z) + + SetBlipSprite(blip, 121) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 27) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("blipTranslateCapnicorn")) + EndTextCommandSetBlipName(blip) end) -- Enter / Exit marker events, and draw markers CreateThread(function() - while true do - local sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == "unicorn" then - local coords = GetEntityCoords(PlayerPedId()) - local isInMarker, currentZone = false - local inVeh = IsPedInAnyVehicle(PlayerPedId()) - - for k, v in pairs(Config.Zones) do - local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) - local distance = #(coords - zonePos) - - if v.Type ~= -1 and distance < Config.DrawDistance then - sleep = 0 - if k == "VehicleDeleter" then - if inVeh then - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - else - DrawMarker( - v.Type, - v.Pos.x, - v.Pos.y, - v.Pos.z, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - v.Color.r, - v.Color.g, - v.Color.b, - 100, - false, - false, - 2, - v.Rotate, - nil, - nil, - false - ) - end - end - - if distance < v.Size.x then - isInMarker, currentZone = true, k - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker, LastZone = true, currentZone - TriggerEvent("bpt_unicornjob:hasEnteredMarker", currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent("bpt_unicornjob:hasExitedMarker", LastZone) - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if ESX.PlayerData.job and ESX.PlayerData.job.name == "unicorn" then + local coords = GetEntityCoords(PlayerPedId()) + local isInMarker, currentZone = false + local inVeh = IsPedInAnyVehicle(PlayerPedId()) + + for k, v in pairs(Config.Zones) do + local zonePos = vector3(v.Pos.x, v.Pos.y, v.Pos.z) + local distance = #(coords - zonePos) + + if v.Type ~= -1 and distance < Config.DrawDistance then + sleep = 0 + if k == "VehicleDeleter" then + if inVeh then + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + else + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, false, 2, v.Rotate, nil, nil, false) + end + end + + if distance < v.Size.x then + isInMarker, currentZone = true, k + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker, LastZone = true, currentZone + TriggerEvent("bpt_unicornjob:hasEnteredMarker", currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("bpt_unicornjob:hasExitedMarker", LastZone) + end + end + Wait(sleep) + end end) -- Key Controls CreateThread(function() - while true do - local sleep = 1500 - if CurrentAction and not ESX.PlayerData.dead then - sleep = 0 - ESX.ShowHelpNotification(CurrentActionMsg) - - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "unicorn" then - if CurrentAction == "unicorn_actions_menu" then - OpenUnicornActionsMenu() - elseif CurrentAction == "cloakroom" then - OpenCloakroom() - elseif CurrentAction == "vehicle_spawner" then - OpenVehicleSpawnerMenu() - elseif CurrentAction == "delete_vehicle" then - DeleteJobVehicle() - end - - CurrentAction = nil - end - end - Wait(sleep) - end + while true do + local sleep = 1500 + if CurrentAction and not ESX.PlayerData.dead then + sleep = 0 + ESX.ShowHelpNotification(CurrentActionMsg) + + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "unicorn" then + if CurrentAction == "unicorn_actions_menu" then + OpenUnicornActionsMenu() + elseif CurrentAction == "cloakroom" then + OpenCloakroom() + elseif CurrentAction == "vehicle_spawner" then + OpenVehicleSpawnerMenu() + elseif CurrentAction == "delete_vehicle" then + DeleteJobVehicle() + end + + CurrentAction = nil + end + end + Wait(sleep) + end end) RegisterCommand("unicornmenu", function() - if - not ESX.PlayerData.dead - and Config.EnablePlayerManagement - and ESX.PlayerData.job - and ESX.PlayerData.job.name == "unicorn" - then - OpenMobileUnicornActionsMenu() - end + if not ESX.PlayerData.dead and Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.name == "unicorn" then + OpenMobileUnicornActionsMenu() + end end, false) RegisterKeyMapping("unicornmenu", "Open Unicorn Menu", "keyboard", "f6") diff --git a/server-data/resources/[bpt_addons]/bpt_vehicletax/server/server.lua b/server-data/resources/[bpt_addons]/bpt_vehicletax/server/server.lua index ae4b37ac3..f723d7a2d 100644 --- a/server-data/resources/[bpt_addons]/bpt_vehicletax/server/server.lua +++ b/server-data/resources/[bpt_addons]/bpt_vehicletax/server/server.lua @@ -3,43 +3,40 @@ local percentage = 1 ESX = exports["es_extended"]:getSharedObject() MySQL.ready(function() - local result = MySQL.Sync.fetchAll("SELECT * FROM vehicles") - for i = 1, #result, 1 do - if vehicleprices[(GetHashKey(result[i].model))] == nil then - table.insert(vehicleprices, { model = GetHashKey(result[i].model), price = result[i].price }) - end - end + local result = MySQL.Sync.fetchAll("SELECT * FROM vehicles") + for i = 1, #result, 1 do + if vehicleprices[(GetHashKey(result[i].model))] == nil then + table.insert(vehicleprices, { model = GetHashKey(result[i].model), price = result[i].price }) + end + end end) function Tax() - local result = MySQL.Sync.fetchAll("SELECT * FROM owned_vehicles") - local xPlayers = ESX.GetPlayers() + local result = MySQL.Sync.fetchAll("SELECT * FROM owned_vehicles") + local xPlayers = ESX.GetPlayers() - for i = 1, #result, 1 do - if result[i].job == "" or result[i].job == nil then - local sqlplayer = ESX.GetPlayerFromIdentifier(result[i].owner) + for i = 1, #result, 1 do + if result[i].job == "" or result[i].job == nil then + local sqlplayer = ESX.GetPlayerFromIdentifier(result[i].owner) - if sqlplayer ~= nil then - for j = 1, #xPlayers, 1 do - local xPlayer = ESX.GetPlayerFromId(xPlayers[j]) + if sqlplayer ~= nil then + for j = 1, #xPlayers, 1 do + local xPlayer = ESX.GetPlayerFromId(xPlayers[j]) - if xPlayer.identifier == result[i].owner then - local model = json.decode(result[i].vehicle).model + if xPlayer.identifier == result[i].owner then + local model = json.decode(result[i].vehicle).model - for m = 1, #vehicleprices, 1 do - if vehicleprices[m].model == model then - TriggerEvent("esx_billing:sendBill", xPlayer[j], "society_cardealer", - TranslateCap("vehicle_tax") .. result[i].plate, - ((vehicleprices[m].price * percentage) / 100), 1 - ) - break - end - end - end - end - end - end - end + for m = 1, #vehicleprices, 1 do + if vehicleprices[m].model == model then + TriggerEvent("bpt_billing:sendBill", xPlayer[j], "society_cardealer", TranslateCap("vehicle_tax") .. result[i].plate, ((vehicleprices[m].price * percentage) / 100), 1) + break + end + end + end + end + end + end + end end TriggerEvent("cron", 24, 0, Tax) diff --git a/server-data/resources/[esx_addons]/esx_billing/README.md b/server-data/resources/[esx_addons]/esx_billing/README.md deleted file mode 100644 index 65b38b761..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# esx_billing - -## Usage -Press `[F7]` To show the billing menu - -When payment trigger is called , pass a boolean at the end to convert payment into split payment. -```lua -TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_mechanic', _U('mechanic'), amount, true) -``` - -```lua -local amount = 100 -local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - -if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification('There\'s no players nearby!') -else - TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_taxi', 'Taxi', amount) -end -``` \ No newline at end of file diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/br.lua b/server-data/resources/[esx_addons]/esx_billing/locales/br.lua deleted file mode 100644 index 09c61d70a..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/br.lua +++ /dev/null @@ -1,10 +0,0 @@ -Locales["br"] = { - ["invoices"] = "faturas", - ["invoices_item"] = "$%s", - ["received_invoice"] = "você ~r~recebeu~s~ uma fatura", - ["paid_invoice"] = "você ~g~pagou~s~ uma fatura de ~r~$%s~s~", - ["received_payment"] = "você ~g~recebeu~s~ um pagamento de ~r~$%s~s~", - ["player_not_online"] = "o jogador não está logado", - ["no_money"] = "you do not have enough money to pay this bill", - ["target_no_money"] = "the player ~r~does not~s~ have enough money to pay the bill!", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/cs.lua b/server-data/resources/[esx_addons]/esx_billing/locales/cs.lua deleted file mode 100644 index 58b9062eb..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/cs.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["cs"] = { - ["invoices"] = "faktury", - ["invoices_item"] = "$%s", - ["received_invoice"] = "právě jsi ~r~obdrzel fakturu", - ["paid_invoice"] = "zaplatil jsi fakturu za ~r~$%s", - ["no_invoices"] = "momentalne nemas zadnou fatkuru k zaplaceni", - ["received_payment"] = "obdržel jsi platbu za ~r~$%s", - ["player_not_online"] = "hráč není přihlášen", - ["no_money"] = "nemáš dostatek peněz na zaplacení této faktury", - ["target_no_money"] = "hráč ~r~nemá dostatek peněz na zaplacení faktury!", - ["keymap_showbills"] = "otevrit menu faktur", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/da.lua b/server-data/resources/[esx_addons]/esx_billing/locales/da.lua deleted file mode 100644 index c20317ae0..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/da.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["da"] = { - ["invoices"] = "regninger", - ["invoices_item"] = "DKK%s", - ["received_invoice"] = "du har lige ~r~modtaget en faktura", - ["paid_invoice"] = "du har betalt en faktura på ~r~DKK%s", - ["no_invoices"] = "du har ingen regninger at betale i øjeblikket", - ["received_payment"] = "du har modtaget en betaling på ~r~DKK%s", - ["player_not_online"] = "spilleren er ikke online", - ["no_money"] = "du har ikke penge nok til at betale denne regning", - ["target_no_money"] = "spilleren ~r~har ikke penge nok til at betale regningen!", - ["keymap_showbills"] = "åbne regninger menu", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/de.lua b/server-data/resources/[esx_addons]/esx_billing/locales/de.lua deleted file mode 100644 index b1af181ed..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/de.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["de"] = { - ["invoices"] = "Rechnungen", - ["invoices_item"] = "%s€", - ["received_invoice"] = "Du hast eine ~r~Rechnung~r~ erhalten!", - ["paid_invoice"] = "Du bezahlst eine Rechung in der Höhe von ~r~%s€", - ["no_invoices"] = "Du hast derzeit keine Rechnung!", - ["received_payment"] = "Du bekommst eine bezahlung von ~r~%s€", - ["player_not_online"] = "Dieser Spieler ist nicht Online!", - ["no_money"] = "Du hast nicht genügend Geld um diese Rechung zu zahlen", - ["target_no_money"] = "Diese Person ~r~hat nicht genug Geld um die Rechnung zu zahlen!", - ["keymap_showbills"] = "Rechnungen Menü Öffnen", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/el.lua b/server-data/resources/[esx_addons]/esx_billing/locales/el.lua deleted file mode 100644 index 847330efd..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/el.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["el"] = { - ["invoices"] = "Αποδείξεις", - ["invoices_item"] = "$%s", - ["received_invoice"] = "Μόλις λάβατε μια απόδειξη", - ["paid_invoice"] = "Πληρώσατε μια απόδειξη αξίας ~r~$%s", - ["no_invoices"] = "Δεν έχετε καμία απόδειξη να πληρώσετε αυτήν τη στιγμή", - ["received_payment"] = "Λάβατε μια πληρωμή αξίας ~r~$%s", - ["player_not_online"] = "Ο παίκτης δεν είναι συνδεδεμένος", - ["no_money"] = "Δεν έχετε αρκετά χρήματα για να πληρώσετε αυτή την απόδειξη", - ["target_no_money"] = "Ο παίκτης ~r~δεν έχει αρκετά χρήματα για να πληρώσει την απόδειξη!", - ["keymap_showbills"] = "Ανοίξτε το μενού αποδείξεων", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/es.lua b/server-data/resources/[esx_addons]/esx_billing/locales/es.lua deleted file mode 100644 index 624e98d34..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/es.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["es"] = { - ["invoices"] = "Facturas", - ["invoices_item"] = "%s$", - ["received_invoice"] = "Has ~r~recibido una multa", - ["paid_invoice"] = "Has pagado una multa de ~r~%s$", - ["no_invoices"] = "No dispones de factuas para pagar ahora mismo", - ["received_payment"] = "Has recibido un pago de %s$", - ["player_not_online"] = "El jugador no está en linea", - ["no_money"] = "No tienes suficiente dinero para pagar la factura", - ["target_no_money"] = "¡El jugador ~r~no tiene suficiente dinero para pagar la factura!", - ["keymap_showbills"] = "Abrir menú de facturas", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/fi.lua b/server-data/resources/[esx_addons]/esx_billing/locales/fi.lua deleted file mode 100644 index 981186acd..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/fi.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["fi"] = { - ["invoices"] = "laskut", - ["invoices_item"] = "$%s", - ["received_invoice"] = "sinä ~r~sait laskun", - ["paid_invoice"] = "sinä maksoit laskun suuruudelta ~r~$%s", - ["no_invoices"] = "you do not have any bills to pay at this moment", - ["received_payment"] = "sinä sait maksun suuruudelta ~r~$%s", - ["player_not_online"] = "pelaaja ei ole sisäänkirjautuneena", - ["no_money"] = "sinulla ei ole tarpeeksi rahaa maksaaksesi tätä laskua.", - ["target_no_money"] = "pelaajalla ~r~ei ole tarpeeksi rahaa maksaakseentätä laskua", - ["keymap_showbills"] = "open bills menu", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/fr.lua b/server-data/resources/[esx_addons]/esx_billing/locales/fr.lua deleted file mode 100644 index 07f9d4730..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/fr.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["fr"] = { - ["invoices"] = "factures", - ["invoices_item"] = "$%s", - ["received_invoice"] = "vous avez ~r~reçu une facture", - ["paid_invoice"] = "vous avez payé une facture de ~r~$%s", - ["no_invoices"] = "vous n'avez aucune facture à payer en ce moment", - ["received_payment"] = "vous avez reçu un paiement de $%s", - ["player_not_online"] = "le joueur n'est pas connecté", - ["no_money"] = "vous n'avez pas assez d'argent pour payer cette facture", - ["target_no_money"] = "le joueur ~r~n'a pas assez d'argent pour payer la facture!", - ["keymap_showbills"] = "ouvrir le menu des factures", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/hu.lua b/server-data/resources/[esx_addons]/esx_billing/locales/hu.lua deleted file mode 100644 index 3774e1f81..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/hu.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["hu"] = { - ["invoices"] = "Számlák", - ["invoices_item"] = "$%s", - ["received_invoice"] = "Kaptál egy számlát", - ["paid_invoice"] = "Befizettél egy számlát ( ~r~$%s )", - ["no_invoices"] = "Nincsen számlád amit kifizethetnél", - ["received_payment"] = "Fizetést kaptál: ~r~$%s", - ["player_not_online"] = "A játékos nem elérhető", - ["no_money"] = "Nincsen elég pénzed, hogy kifizesd ezt a számlát", - ["target_no_money"] = "A játékosnak nincsen annyi pénze, hogy befizesse a számlát", - ["keymap_showbills"] = "Számlák megnézése", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/nl.lua b/server-data/resources/[esx_addons]/esx_billing/locales/nl.lua deleted file mode 100644 index ca887496d..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/nl.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["nl"] = { - ["invoices"] = "Facturen", - ["invoices_item"] = "€%s", - ["received_invoice"] = "Je hebt zojuist een ~r~factuur ontvangen", - ["paid_invoice"] = "Je hebt een factuur betaald van ~r~€%s", - ["no_invoices"] = "Je hoeft momenteel geen facturen te betalen", - ["received_payment"] = "je hebt een bedrag ontvangen van ~r~€%s", - ["player_not_online"] = "de speler is niet online", - ["no_money"] = "je hebt niet genoeg geld om deze factuur te betalen", - ["target_no_money"] = "de speler ~r~heeft niet genoeg geld om te betalen!", - ["keymap_showbills"] = "open factuur menu", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/pl.lua b/server-data/resources/[esx_addons]/esx_billing/locales/pl.lua deleted file mode 100644 index d84bc045b..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/pl.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["pl"] = { - ["invoices"] = "faktury", - ["invoices_item"] = "$%s", - ["received_invoice"] = "właśnie ~r~dostałeś/aś fakture", - ["paid_invoice"] = "Zapłaciłeś/aś fakture: ~r~$%s", - ["no_invoices"] = "you do not have any bills to pay at this moment", - ["received_payment"] = "Otrzymałeś/aś zapłate: ~r~$%s", - ["player_not_online"] = "gracz nie jest zalogowany", - ["no_money"] = "nie masz wystarczająco pieniędzy aby zapłacić tą fakture", - ["target_no_money"] = "gracz ~r~nie posiada wystarczająco pieniędzy aby zapłacić tą fakture!", - ["keymap_showbills"] = "open bills menu", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/sl.lua b/server-data/resources/[esx_addons]/esx_billing/locales/sl.lua deleted file mode 100644 index 5197553c2..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/sl.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["sl"] = { - ["invoices"] = "Položnice", - ["invoices_item"] = "$%s", - ["received_invoice"] = "pravkar ste ~r~prejeli račun", - ["paid_invoice"] = "plačali ste račun v višini ~r~$%s", - ["no_invoices"] = "v tem trenutku nimate nobenih računov za plačilo", - ["received_payment"] = "prejeli ste plačilo ~r~$%s", - ["player_not_online"] = "igralec ni prijavljen", - ["no_money"] = "nimate dovolj denarja za plačilo tega računa", - ["target_no_money"] = "igralec ~r~nima dovolj denarja za plačilo računa!", - ["keymap_showbills"] = "Odpri Položnice", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/sr.lua b/server-data/resources/[esx_addons]/esx_billing/locales/sr.lua deleted file mode 100644 index cda4a14e4..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/sr.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["sr"] = { - ["invoices"] = "Računi", - ["invoices_item"] = "$%s", - ["received_invoice"] = "Vi ste ~r~dobili novi račun", - ["paid_invoice"] = "Platili ste račun od ~r~$%s", - ["no_invoices"] = "Nemate računa za plaćanje trenutno", - ["received_payment"] = "Primili ste uplatu u iznosu od ~r~$%s", - ["player_not_online"] = "Osoba nije tu", - ["no_money"] = "Nemate dovoljno novca da platite račun", - ["target_no_money"] = "Osoba ~r~nema dovoljno novca da plati račun!", - ["keymap_showbills"] = "Otvori Račune", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/sv.lua b/server-data/resources/[esx_addons]/esx_billing/locales/sv.lua deleted file mode 100644 index 0adeca80e..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/sv.lua +++ /dev/null @@ -1,10 +0,0 @@ -Locales["sv"] = { - ["invoices"] = "räkningar", - ["invoices_item"] = "%s SEK", - ["received_invoice"] = "du har ~y~mottagit~s~ en räkning", - ["paid_invoice"] = "du ~y~betalade~s~ precis en räkning på ~g~%s SEK~s~", - ["received_payment"] = "du har ~y~mottagit~s~ en räkning på ~g~%s SEK~s~", - ["player_not_online"] = "personen är inte online", - ["no_money"] = "du har ~r~inte råd~s~ för att kunna betala räkningen", - ["target_no_money"] = "personen har ~r~inte råd~s~ för att betala räkningen", -} diff --git a/server-data/resources/[esx_addons]/esx_billing/locales/zh-cn.lua b/server-data/resources/[esx_addons]/esx_billing/locales/zh-cn.lua deleted file mode 100644 index 0be1096ad..000000000 --- a/server-data/resources/[esx_addons]/esx_billing/locales/zh-cn.lua +++ /dev/null @@ -1,12 +0,0 @@ -Locales["zh-cn"] = { - ["invoices"] = "账单", - ["invoices_item"] = "$%s", - ["received_invoice"] = "新增一笔~r~新的账单! 请及时支付!", - ["paid_invoice"] = "已支付一笔~r~$%s元的账单", - ["no_invoices"] = "当前账户尚无可供支付的账单", - ["received_payment"] = "已收到~r~$%s元的账单支付", - ["player_not_online"] = "指定的玩家尚未登录!", - ["no_money"] = "您没有足够的钱支付此账单", - ["target_no_money"] = "此人暂无~r~足够资金可支付账单!", - ["keymap_showbills"] = "打开我的账单", -} diff --git a/server-data/resources/[esx_addons]/esx_mechanicjob/client/main.lua b/server-data/resources/[esx_addons]/esx_mechanicjob/client/main.lua index fc3268128..2e5ad8dac 100644 --- a/server-data/resources/[esx_addons]/esx_mechanicjob/client/main.lua +++ b/server-data/resources/[esx_addons]/esx_mechanicjob/client/main.lua @@ -1,950 +1,949 @@ local HasAlreadyEnteredMarker, LastZone = false, nil -local CurrentAction, CurrentActionMsg, CurrentActionData = nil, '', {} +local CurrentAction, CurrentActionMsg, CurrentActionData = nil, "", {} local CurrentlyTowedVehicle, Blips, NPCOnJob, NPCTargetTowable, NPCTargetTowableZone = nil, {}, false, nil, nil local NPCHasSpawnedTowable, NPCLastCancel, NPCHasBeenNextToTowable, NPCTargetDeleterZone = false, GetGameTimer() - 5 * 60000, false, false local isDead, isBusy = false, false function SelectRandomTowable() - local index = GetRandomIntInRange(1, #Config.Towables) + local index = GetRandomIntInRange(1, #Config.Towables) - for k,v in pairs(Config.Zones) do - if v.Pos.x == Config.Towables[index].x and v.Pos.y == Config.Towables[index].y and v.Pos.z == Config.Towables[index].z then - return k - end - end + for k, v in pairs(Config.Zones) do + if v.Pos.x == Config.Towables[index].x and v.Pos.y == Config.Towables[index].y and v.Pos.z == Config.Towables[index].z then + return k + end + end end function StartNPCJob() - NPCOnJob = true + NPCOnJob = true - NPCTargetTowableZone = SelectRandomTowable() - local zone = Config.Zones[NPCTargetTowableZone] + NPCTargetTowableZone = SelectRandomTowable() + local zone = Config.Zones[NPCTargetTowableZone] - Blips['NPCTargetTowableZone'] = AddBlipForCoord(zone.Pos.x, zone.Pos.y, zone.Pos.z) - SetBlipRoute(Blips['NPCTargetTowableZone'], true) + Blips["NPCTargetTowableZone"] = AddBlipForCoord(zone.Pos.x, zone.Pos.y, zone.Pos.z) + SetBlipRoute(Blips["NPCTargetTowableZone"], true) - ESX.ShowNotification(TranslateCap('drive_to_indicated')) + ESX.ShowNotification(TranslateCap("drive_to_indicated")) end function StopNPCJob(cancel) - if Blips['NPCTargetTowableZone'] then - RemoveBlip(Blips['NPCTargetTowableZone']) - Blips['NPCTargetTowableZone'] = nil - end - - if Blips['NPCDelivery'] then - RemoveBlip(Blips['NPCDelivery']) - Blips['NPCDelivery'] = nil - end - - Config.Zones.VehicleDelivery.Type = -1 - - NPCOnJob = false - NPCTargetTowable = nil - NPCTargetTowableZone = nil - NPCHasSpawnedTowable = false - NPCHasBeenNextToTowable = false - - if cancel then - ESX.ShowNotification(TranslateCap('mission_canceled'), "error") - end + if Blips["NPCTargetTowableZone"] then + RemoveBlip(Blips["NPCTargetTowableZone"]) + Blips["NPCTargetTowableZone"] = nil + end + + if Blips["NPCDelivery"] then + RemoveBlip(Blips["NPCDelivery"]) + Blips["NPCDelivery"] = nil + end + + Config.Zones.VehicleDelivery.Type = -1 + + NPCOnJob = false + NPCTargetTowable = nil + NPCTargetTowableZone = nil + NPCHasSpawnedTowable = false + NPCHasBeenNextToTowable = false + + if cancel then + ESX.ShowNotification(TranslateCap("mission_canceled"), "error") + end end function OpenMechanicActionsMenu() - local elements = { - {unselectable = true, icon = "fas fa-gear", title = TranslateCap('mechanic')}, - {icon = "fas fa-car", title = TranslateCap('vehicle_list'), value = 'vehicle_list'}, - {icon = "fas fa-shirt", title = TranslateCap('work_wear'), value = 'cloakroom'}, - {icon = "fas fa-shirt", title = TranslateCap('civ_wear'), value = 'cloakroom2'}, - {icon = "fas fa-box", title = TranslateCap('deposit_stock'), value = 'put_stock'}, - {icon = "fas fa-box", title = TranslateCap('withdraw_stock'), value = 'get_stock'} - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name == 'boss' then - elements[#elements+1] = { - icon = 'fas fa-boss', - title = TranslateCap('boss_actions'), - value = 'boss_actions' - } - end - - ESX.OpenContext("right", elements, function(menu,element) - if element.value == 'vehicle_list' then - if Config.EnableSocietyOwnedVehicles then - local elements2 = { - {unselectable = true, icon = "fas fa-car", title = TranslateCap('service_vehicle')} - } - - ESX.TriggerServerCallback('esx_society:getVehiclesInGarage', function(vehicles) - for i=1, #vehicles, 1 do - elements2[#elements2+1] = { - icon = 'fas fa-car', - title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. ' [' .. vehicles[i].plate .. ']', - value = vehicles[i] - } - end - - ESX.OpenContext("right", elements2, function(menu2,element2) - ESX.CloseContext() - local vehicleProps = element2.value - - ESX.Game.SpawnVehicle(vehicleProps.model, Config.Zones.VehicleSpawnPoint.Pos, 270.0, function(vehicle) - ESX.Game.SetVehicleProperties(vehicle, vehicleProps) - local playerPed = PlayerPedId() - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - end) - - TriggerServerEvent('esx_society:removeVehicleFromGarage', 'mechanic', vehicleProps) - end) - end, 'mechanic') - else - local elements2 = { - {unselectable = true, icon = "fas fa-car", title = TranslateCap('service_vehicle')}, - {icon = "fas fa-truck", title = TranslateCap('flat_bed'), value = 'flatbed'}, - {icon = "fas fa-truck", title = TranslateCap('tow_truck'), value = 'towtruck2'} - } - - if Config.EnablePlayerManagement and ESX.PlayerData.job and (ESX.PlayerData.job.grade_name == 'boss' or ESX.PlayerData.job.grade_name == 'chief' or ESX.PlayerData.job.grade_name == 'experimente') then - elements2[#elements2+1] = { - icon = 'fas fa-truck', - title = 'Slamvan', - value = 'slamvan3' - } - end - - ESX.OpenContext("right", elements2, function(menu2,element2) - if Config.MaxInService == -1 then - ESX.CloseContext() - ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) - local playerPed = PlayerPedId() - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - end) - else - ESX.TriggerServerCallback('esx_service:enableService', function(canTakeService, maxInService, inServiceCount) - if canTakeService then - ESX.CloseContext() - ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) - local playerPed = PlayerPedId() - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - end) - else - ESX.ShowNotification(TranslateCap('service_full') .. inServiceCount .. '/' .. maxInService) - end - end, 'mechanic') - end - end) - end - elseif element.value == 'cloakroom' then - ESX.CloseContext() - 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) - elseif element.value == 'cloakroom2' then - ESX.CloseContext() - ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin) - TriggerEvent('skinchanger:loadSkin', skin) - end) - elseif Config.OxInventory and (element.value == 'put_stock' or element.value == 'get_stock') then - exports.ox_inventory:openInventory('stash', 'society_mechanic') - return ESX.CloseContext() - elseif element.value == 'put_stock' then - OpenPutStocksMenu() - elseif element.value == 'get_stock' then - OpenGetStocksMenu() - elseif element.value == 'boss_actions' then - TriggerEvent('esx_society:openBossMenu', 'mechanic', function(data, menu) - ESX.CloseContext() - end) - end - end, function(menu) - CurrentAction = 'mechanic_actions_menu' - CurrentActionMsg = TranslateCap('open_actions') - CurrentActionData = {} - end) + local elements = { + { unselectable = true, icon = "fas fa-gear", title = TranslateCap("mechanic") }, + { icon = "fas fa-car", title = TranslateCap("vehicle_list"), value = "vehicle_list" }, + { icon = "fas fa-shirt", title = TranslateCap("work_wear"), value = "cloakroom" }, + { icon = "fas fa-shirt", title = TranslateCap("civ_wear"), value = "cloakroom2" }, + { icon = "fas fa-box", title = TranslateCap("deposit_stock"), value = "put_stock" }, + { icon = "fas fa-box", title = TranslateCap("withdraw_stock"), value = "get_stock" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name == "boss" then + elements[#elements + 1] = { + icon = "fas fa-boss", + title = TranslateCap("boss_actions"), + value = "boss_actions", + } + end + + ESX.OpenContext("right", elements, function(menu, element) + if element.value == "vehicle_list" then + if Config.EnableSocietyOwnedVehicles then + local elements2 = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("service_vehicle") }, + } + + ESX.TriggerServerCallback("esx_society:getVehiclesInGarage", function(vehicles) + for i = 1, #vehicles, 1 do + elements2[#elements2 + 1] = { + icon = "fas fa-car", + title = GetDisplayNameFromVehicleModel(vehicles[i].model) .. " [" .. vehicles[i].plate .. "]", + value = vehicles[i], + } + end + + ESX.OpenContext("right", elements2, function(menu2, element2) + ESX.CloseContext() + local vehicleProps = element2.value + + ESX.Game.SpawnVehicle(vehicleProps.model, Config.Zones.VehicleSpawnPoint.Pos, 270.0, function(vehicle) + ESX.Game.SetVehicleProperties(vehicle, vehicleProps) + local playerPed = PlayerPedId() + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + end) + + TriggerServerEvent("esx_society:removeVehicleFromGarage", "mechanic", vehicleProps) + end) + end, "mechanic") + else + local elements2 = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("service_vehicle") }, + { icon = "fas fa-truck", title = TranslateCap("flat_bed"), value = "flatbed" }, + { icon = "fas fa-truck", title = TranslateCap("tow_truck"), value = "towtruck2" }, + } + + if Config.EnablePlayerManagement and ESX.PlayerData.job and (ESX.PlayerData.job.grade_name == "boss" or ESX.PlayerData.job.grade_name == "chief" or ESX.PlayerData.job.grade_name == "experimente") then + elements2[#elements2 + 1] = { + icon = "fas fa-truck", + title = "Slamvan", + value = "slamvan3", + } + end + + ESX.OpenContext("right", elements2, function(menu2, element2) + if Config.MaxInService == -1 then + ESX.CloseContext() + ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) + local playerPed = PlayerPedId() + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + end) + else + ESX.TriggerServerCallback("esx_service:enableService", function(canTakeService, maxInService, inServiceCount) + if canTakeService then + ESX.CloseContext() + ESX.Game.SpawnVehicle(element2.value, Config.Zones.VehicleSpawnPoint.Pos, 90.0, function(vehicle) + local playerPed = PlayerPedId() + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + end) + else + ESX.ShowNotification(TranslateCap("service_full") .. inServiceCount .. "/" .. maxInService) + end + end, "mechanic") + end + end) + end + elseif element.value == "cloakroom" then + ESX.CloseContext() + 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) + elseif element.value == "cloakroom2" then + ESX.CloseContext() + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + elseif Config.OxInventory and (element.value == "put_stock" or element.value == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_mechanic") + return ESX.CloseContext() + elseif element.value == "put_stock" then + OpenPutStocksMenu() + elseif element.value == "get_stock" then + OpenGetStocksMenu() + elseif element.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "mechanic", function(data, menu) + ESX.CloseContext() + end) + end + end, function(menu) + CurrentAction = "mechanic_actions_menu" + CurrentActionMsg = TranslateCap("open_actions") + CurrentActionData = {} + end) end function OpenMechanicHarvestMenu() - if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= 'recrue' then - local elements = { - {unselectable = true, icon = "fas fa-gear", title = "Mechanic Harvest Menu"}, - {icon = "fas fa-gear", title = TranslateCap('gas_can'), value = 'gaz_bottle'}, - {icon = "fas fa-gear", title = TranslateCap('repair_tools'), value = 'fix_tool'}, - {icon = "fas fa-gear", title = TranslateCap('body_work_tools'), value = 'caro_tool'} - } - - ESX.OpenContext("right", elements, function(menu,element) - if element.value == 'gaz_bottle' then - TriggerServerEvent('esx_mechanicjob:startHarvest') - elseif element.value == 'fix_tool' then - TriggerServerEvent('esx_mechanicjob:startHarvest2') - elseif element.value == 'caro_tool' then - TriggerServerEvent('esx_mechanicjob:startHarvest3') - end - end, function(menu) - CurrentAction = 'mechanic_harvest_menu' - CurrentActionMsg = TranslateCap('harvest_menu') - CurrentActionData = {} - end) - else - ESX.ShowNotification(TranslateCap('not_experienced_enough')) - end + if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= "recrue" then + local elements = { + { unselectable = true, icon = "fas fa-gear", title = "Mechanic Harvest Menu" }, + { icon = "fas fa-gear", title = TranslateCap("gas_can"), value = "gaz_bottle" }, + { icon = "fas fa-gear", title = TranslateCap("repair_tools"), value = "fix_tool" }, + { icon = "fas fa-gear", title = TranslateCap("body_work_tools"), value = "caro_tool" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + if element.value == "gaz_bottle" then + TriggerServerEvent("esx_mechanicjob:startHarvest") + elseif element.value == "fix_tool" then + TriggerServerEvent("esx_mechanicjob:startHarvest2") + elseif element.value == "caro_tool" then + TriggerServerEvent("esx_mechanicjob:startHarvest3") + end + end, function(menu) + CurrentAction = "mechanic_harvest_menu" + CurrentActionMsg = TranslateCap("harvest_menu") + CurrentActionData = {} + end) + else + ESX.ShowNotification(TranslateCap("not_experienced_enough")) + end end function OpenMechanicCraftMenu() - if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= 'recrue' then - local elements = { - {unselectable = true, icon = "fas fa-gear", title = "Mechanic Craft Menu"}, - {icon = "fas fa-gear", title = TranslateCap('blowtorch'), value = 'blow_pipe'}, - {icon = "fas fa-gear", title = TranslateCap('repair_kit'), value = 'fix_kit'}, - {icon = "fas fa-gear", title = TranslateCap('body_kit'), value = 'caro_kit'} - } - - ESX.OpenContext("right", elements, function(menu,element) - if element.value == 'blow_pipe' then - TriggerServerEvent('esx_mechanicjob:startCraft') - elseif element.value == 'fix_kit' then - TriggerServerEvent('esx_mechanicjob:startCraft2') - elseif element.value == 'caro_kit' then - TriggerServerEvent('esx_mechanicjob:startCraft3') - end - end, function(menu) - CurrentAction = 'mechanic_craft_menu' - CurrentActionMsg = TranslateCap('craft_menu') - CurrentActionData = {} - end) - else - ESX.ShowNotification(TranslateCap('not_experienced_enough')) - end + if Config.EnablePlayerManagement and ESX.PlayerData.job and ESX.PlayerData.job.grade_name ~= "recrue" then + local elements = { + { unselectable = true, icon = "fas fa-gear", title = "Mechanic Craft Menu" }, + { icon = "fas fa-gear", title = TranslateCap("blowtorch"), value = "blow_pipe" }, + { icon = "fas fa-gear", title = TranslateCap("repair_kit"), value = "fix_kit" }, + { icon = "fas fa-gear", title = TranslateCap("body_kit"), value = "caro_kit" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + if element.value == "blow_pipe" then + TriggerServerEvent("esx_mechanicjob:startCraft") + elseif element.value == "fix_kit" then + TriggerServerEvent("esx_mechanicjob:startCraft2") + elseif element.value == "caro_kit" then + TriggerServerEvent("esx_mechanicjob:startCraft3") + end + end, function(menu) + CurrentAction = "mechanic_craft_menu" + CurrentActionMsg = TranslateCap("craft_menu") + CurrentActionData = {} + end) + else + ESX.ShowNotification(TranslateCap("not_experienced_enough")) + end end function OpenMobileMechanicActionsMenu() - local elements = { - {unselectable = true, icon = "fas fa-gear", title = TranslateCap('mechanic')}, - {icon = "fas fa-gear", title = TranslateCap('billing'), value = 'billing'}, - {icon = "fas fa-gear", title = TranslateCap('hijack'), value = 'hijack_vehicle'}, - {icon = "fas fa-gear", title = TranslateCap('repair'), value = 'fix_vehicle'}, - {icon = "fas fa-gear", title = TranslateCap('clean'), value = 'clean_vehicle'}, - {icon = "fas fa-gear", title = TranslateCap('imp_veh'), value = 'del_vehicle'}, - {icon = "fas fa-gear", title = TranslateCap('flat_bed'), value = 'dep_vehicle'}, - {icon = "fas fa-gear", title = TranslateCap('place_objects'), value = 'object_spawner'} - } - - ESX.OpenContext("right", elements, function(menu,element) - if isBusy then return end - - if element.value == "billing" then - local elements2 = { - {unselectable = true, icon = "fas fa-scroll", title = element.title}, - {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.."}, - {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} - } - - ESX.OpenContext("right", elements2, function(menu2,element2) - local amount = tonumber(menu2.eles[2].inputValue) - - if amount == nil or amount < 0 then - ESX.ShowNotification(TranslateCap('amount_invalid'), "error") - else - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap('no_players_nearby'), "error") - else - ESX.CloseContext() - TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_mechanic', TranslateCap('mechanic'), amount) - end - end - end) - elseif element.value == "hijack_vehicle" then - local playerPed = PlayerPedId() - local vehicle = ESX.Game.GetVehicleInDirection() - local coords = GetEntityCoords(playerPed) - - if IsPedSittingInAnyVehicle(playerPed) then - ESX.ShowNotification(TranslateCap('inside_vehicle')) - return - end - - if DoesEntityExist(vehicle) then - isBusy = true - TaskStartScenarioInPlace(playerPed, 'WORLD_HUMAN_WELDING', 0, true) - CreateThread(function() - Wait(10000) - - SetVehicleDoorsLocked(vehicle, 1) - SetVehicleDoorsLockedForAllPlayers(vehicle, false) - ClearPedTasksImmediately(playerPed) - - ESX.ShowNotification(TranslateCap('vehicle_unlocked')) - isBusy = false - end) - else - ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) - end - elseif element.value == "fix_vehicle" then - local playerPed = PlayerPedId() - local vehicle = ESX.Game.GetVehicleInDirection() - local coords = GetEntityCoords(playerPed) - - if IsPedSittingInAnyVehicle(playerPed) then - ESX.ShowNotification(TranslateCap('inside_vehicle')) - return - end - - if DoesEntityExist(vehicle) then - isBusy = true - TaskStartScenarioInPlace(playerPed, 'PROP_HUMAN_BUM_BIN', 0, true) - CreateThread(function() - Wait(20000) - - SetVehicleFixed(vehicle) - SetVehicleDeformationFixed(vehicle) - SetVehicleUndriveable(vehicle, false) - SetVehicleEngineOn(vehicle, true, true) - ClearPedTasksImmediately(playerPed) - - ESX.ShowNotification(TranslateCap('vehicle_repaired')) - isBusy = false - end) - else - ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) - end - elseif element.value == "clean_vehicle" then - local playerPed = PlayerPedId() - local vehicle = ESX.Game.GetVehicleInDirection() - local coords = GetEntityCoords(playerPed) - - if IsPedSittingInAnyVehicle(playerPed) then - ESX.ShowNotification(TranslateCap('inside_vehicle')) - return - end - - if DoesEntityExist(vehicle) then - isBusy = true - TaskStartScenarioInPlace(playerPed, 'WORLD_HUMAN_MAID_CLEAN', 0, true) - CreateThread(function() - Wait(10000) - - SetVehicleDirtLevel(vehicle, 0) - ClearPedTasksImmediately(playerPed) - - ESX.ShowNotification(TranslateCap('vehicle_cleaned')) - isBusy = false - end) - else - ESX.ShowNotification(TranslateCap('no_vehicle_nearby')) - end - elseif element.value == "del_vehicle" then - local playerPed = PlayerPedId() - - if IsPedSittingInAnyVehicle(playerPed) then - local vehicle = GetVehiclePedIsIn(playerPed, false) - - if GetPedInVehicleSeat(vehicle, -1) == playerPed then - ESX.ShowNotification(TranslateCap('vehicle_impounded')) - ESX.Game.DeleteVehicle(vehicle) - else - ESX.ShowNotification(TranslateCap('must_seat_driver')) - end - else - local vehicle = ESX.Game.GetVehicleInDirection() - - if DoesEntityExist(vehicle) then - ESX.ShowNotification(TranslateCap('vehicle_impounded')) - ESX.Game.DeleteVehicle(vehicle) - else - ESX.ShowNotification(TranslateCap('must_near')) - end - end - elseif element.value == "dep_vehicle" then - local playerPed = PlayerPedId() - local vehicle = GetVehiclePedIsIn(playerPed, true) - - local towmodel = `flatbed` - local isVehicleTow = IsVehicleModel(vehicle, towmodel) - - if isVehicleTow then - local targetVehicle = ESX.Game.GetVehicleInDirection() - - if CurrentlyTowedVehicle == nil then - if targetVehicle ~= 0 then - if not IsPedInAnyVehicle(playerPed, true) then - if vehicle ~= targetVehicle then - AttachEntityToEntity(targetVehicle, vehicle, 20, -0.5, -5.0, 1.0, 0.0, 0.0, 0.0, false, false, false, false, 20, true) - CurrentlyTowedVehicle = targetVehicle - ESX.ShowNotification(TranslateCap('vehicle_success_attached')) - - if NPCOnJob then - if NPCTargetTowable == targetVehicle then - ESX.ShowNotification(TranslateCap('please_drop_off')) - Config.Zones.VehicleDelivery.Type = 1 - - if Blips['NPCTargetTowableZone'] then - RemoveBlip(Blips['NPCTargetTowableZone']) - Blips['NPCTargetTowableZone'] = nil - end - - Blips['NPCDelivery'] = AddBlipForCoord(Config.Zones.VehicleDelivery.Pos.x, Config.Zones.VehicleDelivery.Pos.y, Config.Zones.VehicleDelivery.Pos.z) - SetBlipRoute(Blips['NPCDelivery'], true) - end - end - else - ESX.ShowNotification(TranslateCap('cant_attach_own_tt')) - end - end - else - ESX.ShowNotification(TranslateCap('no_veh_att')) - end - else - AttachEntityToEntity(CurrentlyTowedVehicle, vehicle, 20, -0.5, -12.0, 1.0, 0.0, 0.0, 0.0, false, false, false, false, 20, true) - DetachEntity(CurrentlyTowedVehicle, true, true) - - if NPCOnJob then - if NPCTargetDeleterZone then - - if CurrentlyTowedVehicle == NPCTargetTowable then - ESX.Game.DeleteVehicle(NPCTargetTowable) - TriggerServerEvent('esx_mechanicjob:onNPCJobMissionCompleted') - StopNPCJob() - NPCTargetDeleterZone = false - else - ESX.ShowNotification(TranslateCap('not_right_veh')) - end - - else - ESX.ShowNotification(TranslateCap('not_right_place')) - end - end - - CurrentlyTowedVehicle = nil - ESX.ShowNotification(TranslateCap('veh_det_succ')) - end - else - ESX.ShowNotification(TranslateCap('imp_flatbed')) - end - elseif element.value == "object_spawner" then - local playerPed = PlayerPedId() - - if IsPedSittingInAnyVehicle(playerPed) then - ESX.ShowNotification(TranslateCap('inside_vehicle')) - return - end - - local elements2 = { - {unselectable= true, icon = "fas fa-object", title = TranslateCap('objects')}, - {icon = "fas fa-object", title = TranslateCap('roadcone'), value = 'prop_roadcone02a'}, - {icon = "fas fa-object", title = TranslateCap('toolbox'), value = 'prop_toolchest_01'} - } - - ESX.OpenContext("right", elements2, function(menuObj,elementObj) - local model = elementObj.value - 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 - elseif model == 'prop_toolchest_01' 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) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-gear", title = TranslateCap("mechanic") }, + { icon = "fas fa-gear", title = TranslateCap("billing"), value = "billing" }, + { icon = "fas fa-gear", title = TranslateCap("hijack"), value = "hijack_vehicle" }, + { icon = "fas fa-gear", title = TranslateCap("repair"), value = "fix_vehicle" }, + { icon = "fas fa-gear", title = TranslateCap("clean"), value = "clean_vehicle" }, + { icon = "fas fa-gear", title = TranslateCap("imp_veh"), value = "del_vehicle" }, + { icon = "fas fa-gear", title = TranslateCap("flat_bed"), value = "dep_vehicle" }, + { icon = "fas fa-gear", title = TranslateCap("place_objects"), value = "object_spawner" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + if isBusy then + return + end + + if element.value == "billing" then + local elements2 = { + { unselectable = true, icon = "fas fa-scroll", title = element.title }, + { title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 250000, inputPlaceholder = "Amount to bill.." }, + { icon = "fas fa-check-double", title = "Confirm", value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2, element2) + local amount = tonumber(menu2.eles[2].inputValue) + + if amount == nil or amount < 0 then + ESX.ShowNotification(TranslateCap("amount_invalid"), "error") + else + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players_nearby"), "error") + else + ESX.CloseContext() + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_mechanic", TranslateCap("mechanic"), amount) + end + end + end) + elseif element.value == "hijack_vehicle" then + local playerPed = PlayerPedId() + local vehicle = ESX.Game.GetVehicleInDirection() + local coords = GetEntityCoords(playerPed) + + if IsPedSittingInAnyVehicle(playerPed) then + ESX.ShowNotification(TranslateCap("inside_vehicle")) + return + end + + if DoesEntityExist(vehicle) then + isBusy = true + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_WELDING", 0, true) + CreateThread(function() + Wait(10000) + + SetVehicleDoorsLocked(vehicle, 1) + SetVehicleDoorsLockedForAllPlayers(vehicle, false) + ClearPedTasksImmediately(playerPed) + + ESX.ShowNotification(TranslateCap("vehicle_unlocked")) + isBusy = false + end) + else + ESX.ShowNotification(TranslateCap("no_vehicle_nearby")) + end + elseif element.value == "fix_vehicle" then + local playerPed = PlayerPedId() + local vehicle = ESX.Game.GetVehicleInDirection() + local coords = GetEntityCoords(playerPed) + + if IsPedSittingInAnyVehicle(playerPed) then + ESX.ShowNotification(TranslateCap("inside_vehicle")) + return + end + + if DoesEntityExist(vehicle) then + isBusy = true + TaskStartScenarioInPlace(playerPed, "PROP_HUMAN_BUM_BIN", 0, true) + CreateThread(function() + Wait(20000) + + SetVehicleFixed(vehicle) + SetVehicleDeformationFixed(vehicle) + SetVehicleUndriveable(vehicle, false) + SetVehicleEngineOn(vehicle, true, true) + ClearPedTasksImmediately(playerPed) + + ESX.ShowNotification(TranslateCap("vehicle_repaired")) + isBusy = false + end) + else + ESX.ShowNotification(TranslateCap("no_vehicle_nearby")) + end + elseif element.value == "clean_vehicle" then + local playerPed = PlayerPedId() + local vehicle = ESX.Game.GetVehicleInDirection() + local coords = GetEntityCoords(playerPed) + + if IsPedSittingInAnyVehicle(playerPed) then + ESX.ShowNotification(TranslateCap("inside_vehicle")) + return + end + + if DoesEntityExist(vehicle) then + isBusy = true + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_MAID_CLEAN", 0, true) + CreateThread(function() + Wait(10000) + + SetVehicleDirtLevel(vehicle, 0) + ClearPedTasksImmediately(playerPed) + + ESX.ShowNotification(TranslateCap("vehicle_cleaned")) + isBusy = false + end) + else + ESX.ShowNotification(TranslateCap("no_vehicle_nearby")) + end + elseif element.value == "del_vehicle" then + local playerPed = PlayerPedId() + + if IsPedSittingInAnyVehicle(playerPed) then + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if GetPedInVehicleSeat(vehicle, -1) == playerPed then + ESX.ShowNotification(TranslateCap("vehicle_impounded")) + ESX.Game.DeleteVehicle(vehicle) + else + ESX.ShowNotification(TranslateCap("must_seat_driver")) + end + else + local vehicle = ESX.Game.GetVehicleInDirection() + + if DoesEntityExist(vehicle) then + ESX.ShowNotification(TranslateCap("vehicle_impounded")) + ESX.Game.DeleteVehicle(vehicle) + else + ESX.ShowNotification(TranslateCap("must_near")) + end + end + elseif element.value == "dep_vehicle" then + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, true) + + local towmodel = `flatbed` + local isVehicleTow = IsVehicleModel(vehicle, towmodel) + + if isVehicleTow then + local targetVehicle = ESX.Game.GetVehicleInDirection() + + if CurrentlyTowedVehicle == nil then + if targetVehicle ~= 0 then + if not IsPedInAnyVehicle(playerPed, true) then + if vehicle ~= targetVehicle then + AttachEntityToEntity(targetVehicle, vehicle, 20, -0.5, -5.0, 1.0, 0.0, 0.0, 0.0, false, false, false, false, 20, true) + CurrentlyTowedVehicle = targetVehicle + ESX.ShowNotification(TranslateCap("vehicle_success_attached")) + + if NPCOnJob then + if NPCTargetTowable == targetVehicle then + ESX.ShowNotification(TranslateCap("please_drop_off")) + Config.Zones.VehicleDelivery.Type = 1 + + if Blips["NPCTargetTowableZone"] then + RemoveBlip(Blips["NPCTargetTowableZone"]) + Blips["NPCTargetTowableZone"] = nil + end + + Blips["NPCDelivery"] = AddBlipForCoord(Config.Zones.VehicleDelivery.Pos.x, Config.Zones.VehicleDelivery.Pos.y, Config.Zones.VehicleDelivery.Pos.z) + SetBlipRoute(Blips["NPCDelivery"], true) + end + end + else + ESX.ShowNotification(TranslateCap("cant_attach_own_tt")) + end + end + else + ESX.ShowNotification(TranslateCap("no_veh_att")) + end + else + AttachEntityToEntity(CurrentlyTowedVehicle, vehicle, 20, -0.5, -12.0, 1.0, 0.0, 0.0, 0.0, false, false, false, false, 20, true) + DetachEntity(CurrentlyTowedVehicle, true, true) + + if NPCOnJob then + if NPCTargetDeleterZone then + if CurrentlyTowedVehicle == NPCTargetTowable then + ESX.Game.DeleteVehicle(NPCTargetTowable) + TriggerServerEvent("esx_mechanicjob:onNPCJobMissionCompleted") + StopNPCJob() + NPCTargetDeleterZone = false + else + ESX.ShowNotification(TranslateCap("not_right_veh")) + end + else + ESX.ShowNotification(TranslateCap("not_right_place")) + end + end + + CurrentlyTowedVehicle = nil + ESX.ShowNotification(TranslateCap("veh_det_succ")) + end + else + ESX.ShowNotification(TranslateCap("imp_flatbed")) + end + elseif element.value == "object_spawner" then + local playerPed = PlayerPedId() + + if IsPedSittingInAnyVehicle(playerPed) then + ESX.ShowNotification(TranslateCap("inside_vehicle")) + return + end + + local elements2 = { + { unselectable = true, icon = "fas fa-object", title = TranslateCap("objects") }, + { icon = "fas fa-object", title = TranslateCap("roadcone"), value = "prop_roadcone02a" }, + { icon = "fas fa-object", title = TranslateCap("toolbox"), value = "prop_toolchest_01" }, + } + + ESX.OpenContext("right", elements2, function(menuObj, elementObj) + local model = elementObj.value + 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 + elseif model == "prop_toolchest_01" 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) + end + end) end function OpenGetStocksMenu() - ESX.TriggerServerCallback('esx_mechanicjob:getStockItems', function(items) - local elements = { - {unselectable = true, icon = "fas fa-box", title = TranslateCap('mechanic_stock')} - } - - for i=1, #items, 1 do - elements[#elements+1] = { - icon = 'fas fa-box', - title = 'x' .. items[i].count .. ' ' .. items[i].label, - value = items[i].name - } - end - - ESX.OpenContext("right", elements, function(menu,element) - local itemName = element.value - - local elements2 = { - {unselectable = true, icon = "fas fa-box", title = element.title}, - {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.."}, - {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} - } - - ESX.OpenContext("right", elements2, function(menu2,element2) - local count = tonumber(menu2.eles[2].inputValue) - - if count == nil then - ESX.ShowNotification(TranslateCap('invalid_quantity')) - else - ESX.CloseContext() - TriggerServerEvent('esx_mechanicjob:getStockItem', itemName, count) - - Wait(1000) - OpenGetStocksMenu() - end - end) - end) - end) + ESX.TriggerServerCallback("esx_mechanicjob:getStockItems", function(items) + local elements = { + { unselectable = true, icon = "fas fa-box", title = TranslateCap("mechanic_stock") }, + } + + for i = 1, #items, 1 do + elements[#elements + 1] = { + icon = "fas fa-box", + title = "x" .. items[i].count .. " " .. items[i].label, + value = items[i].name, + } + end + + ESX.OpenContext("right", elements, function(menu, element) + local itemName = element.value + + local elements2 = { + { unselectable = true, icon = "fas fa-box", title = element.title }, + { title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to withdraw.." }, + { icon = "fas fa-check-double", title = "Confirm", value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2, element2) + local count = tonumber(menu2.eles[2].inputValue) + + if count == nil then + ESX.ShowNotification(TranslateCap("invalid_quantity")) + else + ESX.CloseContext() + TriggerServerEvent("esx_mechanicjob:getStockItem", itemName, count) + + Wait(1000) + OpenGetStocksMenu() + end + end) + end) + end) end function OpenPutStocksMenu() - ESX.TriggerServerCallback('esx_mechanicjob:getPlayerInventory', function(inventory) - local elements = { - {unselectable = true, icon = "fas fa-box", title = TranslateCap('inventory')} - } - - for i=1, #inventory.items, 1 do - local item = inventory.items[i] - - if item.count > 0 then - elements[#elements+1] = { - icon = 'fas fa-box', - title = item.label .. ' x' .. item.count, - type = 'item_standard', - value = item.name - } - end - end - - ESX.OpenContext("right", elements, function(menu,element) - local itemName = element.value - - local elements2 = { - {unselectable = true, icon = "fas fa-box", title = element.title}, - {title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.."}, - {icon = "fas fa-check-double", title = "Confirm", value = "confirm"} - } - - ESX.OpenContext("right", elements2, function(menu2,element2) - local count = tonumber(menu2.eles[2].inputValue) - - if count == nil then - ESX.ShowNotification(TranslateCap('invalid_quantity')) - else - ESX.CloseContext() - TriggerServerEvent('esx_mechanicjob:putStockItems', itemName, count) - - Wait(1000) - OpenPutStocksMenu() - end - end) - end) - end) + ESX.TriggerServerCallback("esx_mechanicjob:getPlayerInventory", function(inventory) + local elements = { + { unselectable = true, icon = "fas fa-box", title = TranslateCap("inventory") }, + } + + for i = 1, #inventory.items, 1 do + local item = inventory.items[i] + + if item.count > 0 then + elements[#elements + 1] = { + icon = "fas fa-box", + title = item.label .. " x" .. item.count, + type = "item_standard", + value = item.name, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local itemName = element.value + + local elements2 = { + { unselectable = true, icon = "fas fa-box", title = element.title }, + { title = "Amount", input = true, inputType = "number", inputMin = 1, inputMax = 100, inputPlaceholder = "Amount to deposit.." }, + { icon = "fas fa-check-double", title = "Confirm", value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2, element2) + local count = tonumber(menu2.eles[2].inputValue) + + if count == nil then + ESX.ShowNotification(TranslateCap("invalid_quantity")) + else + ESX.CloseContext() + TriggerServerEvent("esx_mechanicjob:putStockItems", itemName, count) + + Wait(1000) + OpenPutStocksMenu() + end + end) + end) + end) end -RegisterNetEvent('esx_mechanicjob:onHijack') -AddEventHandler('esx_mechanicjob:onHijack', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then - local vehicle - - if IsPedInAnyVehicle(playerPed, false) then - vehicle = GetVehiclePedIsIn(playerPed, false) - else - vehicle = ESX.Game.GetClosestVehicle(coords) - end - - local chance = math.random(100) - local alarm = math.random(100) - - if DoesEntityExist(vehicle) then - if alarm <= 33 then - SetVehicleAlarm(vehicle, true) - StartVehicleAlarm(vehicle) - end - - TaskStartScenarioInPlace(playerPed, 'WORLD_HUMAN_WELDING', 0, true) - - CreateThread(function() - Wait(10000) - if chance <= 66 then - SetVehicleDoorsLocked(vehicle, 1) - SetVehicleDoorsLockedForAllPlayers(vehicle, false) - ClearPedTasksImmediately(playerPed) - ESX.ShowNotification(TranslateCap('veh_unlocked')) - else - ESX.ShowNotification(TranslateCap('hijack_failed')) - ClearPedTasksImmediately(playerPed) - end - end) - end - end +RegisterNetEvent("esx_mechanicjob:onHijack") +AddEventHandler("esx_mechanicjob:onHijack", function() + local playerPed = PlayerPedId() + local coords = GetEntityCoords(playerPed) + + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then + local vehicle + + if IsPedInAnyVehicle(playerPed, false) then + vehicle = GetVehiclePedIsIn(playerPed, false) + else + vehicle = ESX.Game.GetClosestVehicle(coords) + end + + local chance = math.random(100) + local alarm = math.random(100) + + if DoesEntityExist(vehicle) then + if alarm <= 33 then + SetVehicleAlarm(vehicle, true) + StartVehicleAlarm(vehicle) + end + + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_WELDING", 0, true) + + CreateThread(function() + Wait(10000) + if chance <= 66 then + SetVehicleDoorsLocked(vehicle, 1) + SetVehicleDoorsLockedForAllPlayers(vehicle, false) + ClearPedTasksImmediately(playerPed) + ESX.ShowNotification(TranslateCap("veh_unlocked")) + else + ESX.ShowNotification(TranslateCap("hijack_failed")) + ClearPedTasksImmediately(playerPed) + end + end) + end + end end) -RegisterNetEvent('esx_mechanicjob:onCarokit') -AddEventHandler('esx_mechanicjob:onCarokit', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then - local vehicle - - if IsPedInAnyVehicle(playerPed, false) then - vehicle = GetVehiclePedIsIn(playerPed, false) - else - vehicle = ESX.Game.GetClosestVehicle(coords) - end - - if DoesEntityExist(vehicle) then - TaskStartScenarioInPlace(playerPed, 'WORLD_HUMAN_HAMMERING', 0, true) - CreateThread(function() - Wait(10000) - SetVehicleFixed(vehicle) - SetVehicleDeformationFixed(vehicle) - ClearPedTasksImmediately(playerPed) - ESX.ShowNotification(TranslateCap('body_repaired')) - end) - end - end +RegisterNetEvent("esx_mechanicjob:onCarokit") +AddEventHandler("esx_mechanicjob:onCarokit", function() + local playerPed = PlayerPedId() + local coords = GetEntityCoords(playerPed) + + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then + local vehicle + + if IsPedInAnyVehicle(playerPed, false) then + vehicle = GetVehiclePedIsIn(playerPed, false) + else + vehicle = ESX.Game.GetClosestVehicle(coords) + end + + if DoesEntityExist(vehicle) then + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_HAMMERING", 0, true) + CreateThread(function() + Wait(10000) + SetVehicleFixed(vehicle) + SetVehicleDeformationFixed(vehicle) + ClearPedTasksImmediately(playerPed) + ESX.ShowNotification(TranslateCap("body_repaired")) + end) + end + end end) -RegisterNetEvent('esx_mechanicjob:onFixkit') -AddEventHandler('esx_mechanicjob:onFixkit', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then - local vehicle - - if IsPedInAnyVehicle(playerPed, false) then - vehicle = GetVehiclePedIsIn(playerPed, false) - else - vehicle = ESX.Game.GetClosestVehicle(coords) - end - - if DoesEntityExist(vehicle) then - TaskStartScenarioInPlace(playerPed, 'PROP_HUMAN_BUM_BIN', 0, true) - CreateThread(function() - Wait(20000) - SetVehicleFixed(vehicle) - SetVehicleDeformationFixed(vehicle) - SetVehicleUndriveable(vehicle, false) - ClearPedTasksImmediately(playerPed) - ESX.ShowNotification(TranslateCap('veh_repaired')) - end) - end - end +RegisterNetEvent("esx_mechanicjob:onFixkit") +AddEventHandler("esx_mechanicjob:onFixkit", function() + local playerPed = PlayerPedId() + local coords = GetEntityCoords(playerPed) + + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then + local vehicle + + if IsPedInAnyVehicle(playerPed, false) then + vehicle = GetVehiclePedIsIn(playerPed, false) + else + vehicle = ESX.Game.GetClosestVehicle(coords) + end + + if DoesEntityExist(vehicle) then + TaskStartScenarioInPlace(playerPed, "PROP_HUMAN_BUM_BIN", 0, true) + CreateThread(function() + Wait(20000) + SetVehicleFixed(vehicle) + SetVehicleDeformationFixed(vehicle) + SetVehicleUndriveable(vehicle, false) + ClearPedTasksImmediately(playerPed) + ESX.ShowNotification(TranslateCap("veh_repaired")) + end) + end + end end) -RegisterNetEvent('esx:playerLoaded') -AddEventHandler('esx:playerLoaded', function(xPlayer) - ESX.PlayerData = xPlayer - ESX.PlayerLoaded = true +RegisterNetEvent("esx:playerLoaded") +AddEventHandler("esx:playerLoaded", function(xPlayer) + ESX.PlayerData = xPlayer + ESX.PlayerLoaded = true end) -RegisterNetEvent('esx:setJob') -AddEventHandler('esx:setJob', function(job) - ESX.PlayerData.job = job +RegisterNetEvent("esx:setJob") +AddEventHandler("esx:setJob", function(job) + ESX.PlayerData.job = job end) -AddEventHandler('esx_mechanicjob:hasEnteredMarker', function(zone) - if zone == 'NPCJobTargetTowable' then - - elseif zone =='VehicleDelivery' then - NPCTargetDeleterZone = true - elseif zone == 'MechanicActions' then - CurrentAction = 'mechanic_actions_menu' - CurrentActionMsg = TranslateCap('open_actions') - CurrentActionData = {} - elseif zone == 'Garage' then - CurrentAction = 'mechanic_harvest_menu' - CurrentActionMsg = TranslateCap('harvest_menu') - CurrentActionData = {} - elseif zone == 'Craft' then - CurrentAction = 'mechanic_craft_menu' - CurrentActionMsg = TranslateCap('craft_menu') - CurrentActionData = {} - elseif zone == 'VehicleDeleter' then - local playerPed = PlayerPedId() - - if IsPedInAnyVehicle(playerPed, false) then - local vehicle = GetVehiclePedIsIn(playerPed, false) - - CurrentAction = 'delete_vehicle' - CurrentActionMsg = TranslateCap('veh_stored') - CurrentActionData = {vehicle = vehicle} - end - end - ESX.TextUI(CurrentActionMsg) +AddEventHandler("esx_mechanicjob:hasEnteredMarker", function(zone) + if zone == "NPCJobTargetTowable" then + elseif zone == "VehicleDelivery" then + NPCTargetDeleterZone = true + elseif zone == "MechanicActions" then + CurrentAction = "mechanic_actions_menu" + CurrentActionMsg = TranslateCap("open_actions") + CurrentActionData = {} + elseif zone == "Garage" then + CurrentAction = "mechanic_harvest_menu" + CurrentActionMsg = TranslateCap("harvest_menu") + CurrentActionData = {} + elseif zone == "Craft" then + CurrentAction = "mechanic_craft_menu" + CurrentActionMsg = TranslateCap("craft_menu") + CurrentActionData = {} + elseif zone == "VehicleDeleter" then + local playerPed = PlayerPedId() + + if IsPedInAnyVehicle(playerPed, false) then + local vehicle = GetVehiclePedIsIn(playerPed, false) + + CurrentAction = "delete_vehicle" + CurrentActionMsg = TranslateCap("veh_stored") + CurrentActionData = { vehicle = vehicle } + end + end + ESX.TextUI(CurrentActionMsg) end) -AddEventHandler('esx_mechanicjob:hasExitedMarker', function(zone) - if zone =='VehicleDelivery' then - NPCTargetDeleterZone = false - elseif zone == 'Craft' then - TriggerServerEvent('esx_mechanicjob:stopCraft') - TriggerServerEvent('esx_mechanicjob:stopCraft2') - TriggerServerEvent('esx_mechanicjob:stopCraft3') - elseif zone == 'Garage' then - TriggerServerEvent('esx_mechanicjob:stopHarvest') - TriggerServerEvent('esx_mechanicjob:stopHarvest2') - TriggerServerEvent('esx_mechanicjob:stopHarvest3') - end - - CurrentAction = nil - ESX.CloseContext() - ESX.HideUI() +AddEventHandler("esx_mechanicjob:hasExitedMarker", function(zone) + if zone == "VehicleDelivery" then + NPCTargetDeleterZone = false + elseif zone == "Craft" then + TriggerServerEvent("esx_mechanicjob:stopCraft") + TriggerServerEvent("esx_mechanicjob:stopCraft2") + TriggerServerEvent("esx_mechanicjob:stopCraft3") + elseif zone == "Garage" then + TriggerServerEvent("esx_mechanicjob:stopHarvest") + TriggerServerEvent("esx_mechanicjob:stopHarvest2") + TriggerServerEvent("esx_mechanicjob:stopHarvest3") + end + + CurrentAction = nil + ESX.CloseContext() + ESX.HideUI() end) -AddEventHandler('esx_mechanicjob:hasEnteredEntityZone', function(entity) - local playerPed = PlayerPedId() +AddEventHandler("esx_mechanicjob:hasEnteredEntityZone", function(entity) + local playerPed = PlayerPedId() - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' and not IsPedInAnyVehicle(playerPed, false) then - CurrentAction = 'remove_entity' - CurrentActionMsg = TranslateCap('press_remove_obj') - CurrentActionData = {entity = entity} - ESX.TextUI(CurrentActionMsg) - end + if ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" and not IsPedInAnyVehicle(playerPed, false) then + CurrentAction = "remove_entity" + CurrentActionMsg = TranslateCap("press_remove_obj") + CurrentActionData = { entity = entity } + ESX.TextUI(CurrentActionMsg) + end end) -AddEventHandler('esx_mechanicjob:hasExitedEntityZone', function(entity) - if CurrentAction == 'remove_entity' then - CurrentAction = nil - end - ESX.HideUI() +AddEventHandler("esx_mechanicjob:hasExitedEntityZone", function(entity) + if CurrentAction == "remove_entity" then + CurrentAction = nil + end + ESX.HideUI() end) -RegisterNetEvent('esx_phone:loaded') -AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts) - local specialContact = { - name = TranslateCap('mechanic'), - number = 'mechanic', - base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAA4BJREFUWIXtll9oU3cUx7/nJA02aSSlFouWMnXVB0ejU3wcRteHjv1puoc9rA978cUi2IqgRYWIZkMwrahUGfgkFMEZUdg6C+u21z1o3fbgqigVi7NzUtNcmsac40Npltz7S3rvUHzxQODec87vfD+/e0/O/QFv7Q0beV3QeXqmgV74/7H7fZJvuLwv8q/Xeux1gUrNBpN/nmtavdaqDqBK8VT2RDyV2VHmF1lvLERSBtCVynzYmcp+A9WqT9kcVKX4gHUehF0CEVY+1jYTTIwvt7YSIQnCTvsSUYz6gX5uDt7MP7KOKuQAgxmqQ+neUA+I1B1AiXi5X6ZAvKrabirmVYFwAMRT2RMg7F9SyKspvk73hfrtbkMPyIhA5FVqi0iBiEZMMQdAui/8E4GPv0oAJkpc6Q3+6goAAGpWBxNQmTLFmgL3jSJNgQdGv4pMts2EKm7ICJB/aG0xNdz74VEk13UYCx1/twPR8JjDT8wttyLZtkoAxSb8ZDCz0gdfKxWkFURf2v9qTYH7SK7rQIDn0P3nA0ehixvfwZwE0X9vBE/mW8piohhl1WH18UQBhYnre8N/L8b8xQvlx4ACbB4NnzaeRYDnKm0EALCMLXy84hwuTCXL/ExoB1E7qcK/8NCLIq5HcTT0i6u8TYbXUM1cAyyveVq8Xls7XhYrvY/4n3gC8C+dsmAzL1YUiyfWxvHzsy/w/dNd+KjhW2yvv/RfXr7x9QDcmo1he2RBiCCI1Q8jVj9szPNixVfgz+UiIGyDSrcoRu2J16d3I6e1VYvNSQjXpnucAcEPUOkGYZs/l4uUhowt/3kqu1UIv9n90fAY9jT3YBlbRvFTD4fw++wHjhiTRL/bG75t0jI2ITcHb5om4Xgmhv57xpGOg3d/NIqryOR7z+r+MC6qBJB/ZB2t9Om1D5lFm843G/3E3HI7Yh1xDRAfzLQr5EClBf/HBHK462TG2J0OABXeyWDPZ8VqxmBWYscpyghwtTd4EKpDTjCZdCNmzFM9k+4LHXIFACJN94Z6FiFEpKDQw9HndWsEuhnADVMhAUaYJBp9XrcGQKJ4qFE9k+6r2+MG3k5N8VQ22TVglbX2ZwOzX2VvNKr91zmY6S7N6zqZicVT2WNLyVSehESaBhxnOALfMeYX+K/S2yv7wmMAlvwyuR7FxQUyf0fgc/jztfkJr7XeGgC8BJJgWNV8ImT+AAAAAElFTkSuQmCC' - } +RegisterNetEvent("esx_phone:loaded") +AddEventHandler("esx_phone:loaded", function(phoneNumber, contacts) + local specialContact = { + name = TranslateCap("mechanic"), + number = "mechanic", + base64Icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAA4BJREFUWIXtll9oU3cUx7/nJA02aSSlFouWMnXVB0ejU3wcRteHjv1puoc9rA978cUi2IqgRYWIZkMwrahUGfgkFMEZUdg6C+u21z1o3fbgqigVi7NzUtNcmsac40Npltz7S3rvUHzxQODec87vfD+/e0/O/QFv7Q0beV3QeXqmgV74/7H7fZJvuLwv8q/Xeux1gUrNBpN/nmtavdaqDqBK8VT2RDyV2VHmF1lvLERSBtCVynzYmcp+A9WqT9kcVKX4gHUehF0CEVY+1jYTTIwvt7YSIQnCTvsSUYz6gX5uDt7MP7KOKuQAgxmqQ+neUA+I1B1AiXi5X6ZAvKrabirmVYFwAMRT2RMg7F9SyKspvk73hfrtbkMPyIhA5FVqi0iBiEZMMQdAui/8E4GPv0oAJkpc6Q3+6goAAGpWBxNQmTLFmgL3jSJNgQdGv4pMts2EKm7ICJB/aG0xNdz74VEk13UYCx1/twPR8JjDT8wttyLZtkoAxSb8ZDCz0gdfKxWkFURf2v9qTYH7SK7rQIDn0P3nA0ehixvfwZwE0X9vBE/mW8piohhl1WH18UQBhYnre8N/L8b8xQvlx4ACbB4NnzaeRYDnKm0EALCMLXy84hwuTCXL/ExoB1E7qcK/8NCLIq5HcTT0i6u8TYbXUM1cAyyveVq8Xls7XhYrvY/4n3gC8C+dsmAzL1YUiyfWxvHzsy/w/dNd+KjhW2yvv/RfXr7x9QDcmo1he2RBiCCI1Q8jVj9szPNixVfgz+UiIGyDSrcoRu2J16d3I6e1VYvNSQjXpnucAcEPUOkGYZs/l4uUhowt/3kqu1UIv9n90fAY9jT3YBlbRvFTD4fw++wHjhiTRL/bG75t0jI2ITcHb5om4Xgmhv57xpGOg3d/NIqryOR7z+r+MC6qBJB/ZB2t9Om1D5lFm843G/3E3HI7Yh1xDRAfzLQr5EClBf/HBHK462TG2J0OABXeyWDPZ8VqxmBWYscpyghwtTd4EKpDTjCZdCNmzFM9k+4LHXIFACJN94Z6FiFEpKDQw9HndWsEuhnADVMhAUaYJBp9XrcGQKJ4qFE9k+6r2+MG3k5N8VQ22TVglbX2ZwOzX2VvNKr91zmY6S7N6zqZicVT2WNLyVSehESaBhxnOALfMeYX+K/S2yv7wmMAlvwyuR7FxQUyf0fgc/jztfkJr7XeGgC8BJJgWNV8ImT+AAAAAElFTkSuQmCC", + } - TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon) + TriggerEvent("esx_phone:addSpecialContact", specialContact.name, specialContact.number, specialContact.base64Icon) end) -- Pop NPC mission vehicle when inside area CreateThread(function() - while true do - local Sleep = 1500 - - if NPCTargetTowableZone and not NPCHasSpawnedTowable then - Sleep = 0 - local coords = GetEntityCoords(PlayerPedId()) - local zone = Config.Zones[NPCTargetTowableZone] - - if #(coords - zone.Pos) < Config.NPCSpawnDistance then - local model = Config.Vehicles[GetRandomIntInRange(1, #Config.Vehicles)] - - ESX.Game.SpawnVehicle(model, zone.Pos, 0, function(vehicle) - NPCTargetTowable = vehicle - end) - - NPCHasSpawnedTowable = true - end - end - - if NPCTargetTowableZone and NPCHasSpawnedTowable and not NPCHasBeenNextToTowable then - Sleep = 500 - local coords = GetEntityCoords(PlayerPedId()) - local zone = Config.Zones[NPCTargetTowableZone] - - if #(coords - zone.Pos) < Config.NPCNextToDistance then - Sleep = 0 - ESX.ShowNotification(TranslateCap('please_tow')) - NPCHasBeenNextToTowable = true - end - end - Wait(Sleep) - end + while true do + local Sleep = 1500 + + if NPCTargetTowableZone and not NPCHasSpawnedTowable then + Sleep = 0 + local coords = GetEntityCoords(PlayerPedId()) + local zone = Config.Zones[NPCTargetTowableZone] + + if #(coords - zone.Pos) < Config.NPCSpawnDistance then + local model = Config.Vehicles[GetRandomIntInRange(1, #Config.Vehicles)] + + ESX.Game.SpawnVehicle(model, zone.Pos, 0, function(vehicle) + NPCTargetTowable = vehicle + end) + + NPCHasSpawnedTowable = true + end + end + + if NPCTargetTowableZone and NPCHasSpawnedTowable and not NPCHasBeenNextToTowable then + Sleep = 500 + local coords = GetEntityCoords(PlayerPedId()) + local zone = Config.Zones[NPCTargetTowableZone] + + if #(coords - zone.Pos) < Config.NPCNextToDistance then + Sleep = 0 + ESX.ShowNotification(TranslateCap("please_tow")) + NPCHasBeenNextToTowable = true + end + end + Wait(Sleep) + end end) -- Create Blips CreateThread(function() - local blip = AddBlipForCoord(Config.Zones.MechanicActions.Pos.x, Config.Zones.MechanicActions.Pos.y, Config.Zones.MechanicActions.Pos.z) + local blip = AddBlipForCoord(Config.Zones.MechanicActions.Pos.x, Config.Zones.MechanicActions.Pos.y, Config.Zones.MechanicActions.Pos.z) - SetBlipSprite (blip, 446) - SetBlipDisplay(blip, 4) - SetBlipScale (blip, 1.0) - SetBlipColour (blip, 5) - SetBlipAsShortRange(blip, true) + SetBlipSprite(blip, 446) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, 1.0) + SetBlipColour(blip, 5) + SetBlipAsShortRange(blip, true) - BeginTextCommandSetBlipName('STRING') - AddTextComponentSubstringPlayerName(TranslateCap('mechanic')) - EndTextCommandSetBlipName(blip) + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("mechanic")) + EndTextCommandSetBlipName(blip) end) -- Display markers CreateThread(function() - while true do - local Sleep = 2000 - - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' then - Sleep = 500 - local coords, letSleep = GetEntityCoords(PlayerPedId()), true - - for k,v in pairs(Config.Zones) do - if v.Type ~= -1 and #(coords - v.Pos) < Config.DrawDistance then - Sleep = 0 - DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, true, true, 2, true, nil, nil, false) - letSleep = false - end - end - end - Wait(Sleep) - end + while true do + local Sleep = 2000 + + if ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" then + Sleep = 500 + local coords, letSleep = GetEntityCoords(PlayerPedId()), true + + for k, v in pairs(Config.Zones) do + if v.Type ~= -1 and #(coords - v.Pos) < Config.DrawDistance then + Sleep = 0 + DrawMarker(v.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, true, true, 2, true, nil, nil, false) + letSleep = false + end + end + end + Wait(Sleep) + end end) -- Enter / Exit marker events CreateThread(function() - while true do - local Sleep = 500 - - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' then - - local coords = GetEntityCoords(PlayerPedId()) - local isInMarker = false - local currentZone = nil - - for k,v in pairs(Config.Zones) do - if(#(coords - v.Pos) < v.Size.x) then - Sleep = 0 - isInMarker = true - currentZone = k - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker = true - LastZone = currentZone - TriggerEvent('esx_mechanicjob:hasEnteredMarker', currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent('esx_mechanicjob:hasExitedMarker', LastZone) - end - end - Wait(Sleep) - end + while true do + local Sleep = 500 + + if ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" then + local coords = GetEntityCoords(PlayerPedId()) + local isInMarker = false + local currentZone = nil + + for k, v in pairs(Config.Zones) do + if #(coords - v.Pos) < v.Size.x then + Sleep = 0 + isInMarker = true + currentZone = k + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker = true + LastZone = currentZone + TriggerEvent("esx_mechanicjob:hasEnteredMarker", currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("esx_mechanicjob:hasExitedMarker", LastZone) + end + end + Wait(Sleep) + end end) CreateThread(function() - local trackedEntities = { - 'prop_roadcone02a', - 'prop_toolchest_01' - } - - while true do - Wait(500) - - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - local closestDistance = -1 - local closestEntity = nil - - for i=1, #trackedEntities, 1 do - local object = GetClosestObjectOfType(coords, 3.0, joaat(trackedEntities[i]), false, false, false) - - if DoesEntityExist(object) then - local objCoords = GetEntityCoords(object) - local distance = #(coords - objCoords) - - if closestDistance == -1 or closestDistance > distance then - closestDistance = distance - closestEntity = object - end - end - end - - if closestDistance ~= -1 and closestDistance <= 3.0 then - if LastEntity ~= closestEntity then - TriggerEvent('esx_mechanicjob:hasEnteredEntityZone', closestEntity) - LastEntity = closestEntity - end - else - if LastEntity then - TriggerEvent('esx_mechanicjob:hasExitedEntityZone', LastEntity) - LastEntity = nil - end - end - end + local trackedEntities = { + "prop_roadcone02a", + "prop_toolchest_01", + } + + while true do + Wait(500) + + local playerPed = PlayerPedId() + local coords = GetEntityCoords(playerPed) + + local closestDistance = -1 + local closestEntity = nil + + for i = 1, #trackedEntities, 1 do + local object = GetClosestObjectOfType(coords, 3.0, joaat(trackedEntities[i]), false, false, false) + + if DoesEntityExist(object) then + local objCoords = GetEntityCoords(object) + local distance = #(coords - objCoords) + + if closestDistance == -1 or closestDistance > distance then + closestDistance = distance + closestEntity = object + end + end + end + + if closestDistance ~= -1 and closestDistance <= 3.0 then + if LastEntity ~= closestEntity then + TriggerEvent("esx_mechanicjob:hasEnteredEntityZone", closestEntity) + LastEntity = closestEntity + end + else + if LastEntity then + TriggerEvent("esx_mechanicjob:hasExitedEntityZone", LastEntity) + LastEntity = nil + end + end + end end) -- Key Controls CreateThread(function() - while true do - local sleep = 500 - if CurrentAction then - sleep = 0 - if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' then - if CurrentAction == 'mechanic_actions_menu' then - OpenMechanicActionsMenu() - elseif CurrentAction == 'mechanic_harvest_menu' then - OpenMechanicHarvestMenu() - elseif CurrentAction == 'mechanic_craft_menu' then - OpenMechanicCraftMenu() - elseif CurrentAction == 'delete_vehicle' then - if Config.EnableSocietyOwnedVehicles then - - local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) - TriggerServerEvent('esx_society:putVehicleInGarage', 'mechanic', vehicleProps) - else - local entityModel = GetEntityModel(CurrentActionData.vehicle) - - if entityModel == `flatbed` or entityModel == `towtruck2` or entityModel == `slamvan3` then - TriggerServerEvent('esx_service:disableService', 'mechanic') - end - end - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - elseif CurrentAction == 'remove_entity' then - DeleteEntity(CurrentActionData.entity) - end - - CurrentAction = nil - end - end - Wait(sleep) - end + while true do + local sleep = 500 + if CurrentAction then + sleep = 0 + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" then + if CurrentAction == "mechanic_actions_menu" then + OpenMechanicActionsMenu() + elseif CurrentAction == "mechanic_harvest_menu" then + OpenMechanicHarvestMenu() + elseif CurrentAction == "mechanic_craft_menu" then + OpenMechanicCraftMenu() + elseif CurrentAction == "delete_vehicle" then + if Config.EnableSocietyOwnedVehicles then + local vehicleProps = ESX.Game.GetVehicleProperties(CurrentActionData.vehicle) + TriggerServerEvent("esx_society:putVehicleInGarage", "mechanic", vehicleProps) + else + local entityModel = GetEntityModel(CurrentActionData.vehicle) + + if entityModel == `flatbed` or entityModel == `towtruck2` or entityModel == `slamvan3` then + TriggerServerEvent("esx_service:disableService", "mechanic") + end + end + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + elseif CurrentAction == "remove_entity" then + DeleteEntity(CurrentActionData.entity) + end + + CurrentAction = nil + end + end + Wait(sleep) + end end) -RegisterCommand('mechanicMenu', function() - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' then - OpenMobileMechanicActionsMenu() - end +RegisterCommand("mechanicMenu", function() + if ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" then + OpenMobileMechanicActionsMenu() + end end, false) - - -RegisterCommand('mechanicjob', function() - local playerPed = PlayerPedId() - if ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic' then - if NPCOnJob then - if GetGameTimer() - NPCLastCancel > 5 * 60000 then - StopNPCJob(true) - NPCLastCancel = GetGameTimer() - else - ESX.ShowNotification(TranslateCap('wait_five'), "error") - end - else - if IsPedInAnyVehicle(playerPed, false) and IsVehicleModel(GetVehiclePedIsIn(playerPed, false), `flatbed`) then - StartNPCJob() - else - ESX.ShowNotification(TranslateCap('must_in_flatbed'), "error") - end - end - end +RegisterCommand("mechanicjob", function() + local playerPed = PlayerPedId() + if ESX.PlayerData.job and ESX.PlayerData.job.name == "mechanic" then + if NPCOnJob then + if GetGameTimer() - NPCLastCancel > 5 * 60000 then + StopNPCJob(true) + NPCLastCancel = GetGameTimer() + else + ESX.ShowNotification(TranslateCap("wait_five"), "error") + end + else + if IsPedInAnyVehicle(playerPed, false) and IsVehicleModel(GetVehiclePedIsIn(playerPed, false), `flatbed`) then + StartNPCJob() + else + ESX.ShowNotification(TranslateCap("must_in_flatbed"), "error") + end + end + end end, false) -RegisterKeyMapping('mechanicMenu', 'Open Mechanic Menu', 'keyboard', Config.Controls.mechanicMenu) -RegisterKeyMapping('mechanicjob', 'Togggle NPC Job', 'keyboard', Config.Controls.toggleNPCJob) +RegisterKeyMapping("mechanicMenu", "Open Mechanic Menu", "keyboard", Config.Controls.mechanicMenu) +RegisterKeyMapping("mechanicjob", "Togggle NPC Job", "keyboard", Config.Controls.toggleNPCJob) -AddEventHandler('esx:onPlayerDeath', function(data) isDead = true end) -AddEventHandler('esx:onPlayerSpawn', function(spawn) isDead = false end) +AddEventHandler("esx:onPlayerDeath", function(data) + isDead = true +end) +AddEventHandler("esx:onPlayerSpawn", function(spawn) + isDead = false +end) diff --git a/server-data/resources/[esx_addons]/esx_mechanicjob/fxmanifest.lua b/server-data/resources/[esx_addons]/esx_mechanicjob/fxmanifest.lua index b7a5535c6..f4e210ddb 100644 --- a/server-data/resources/[esx_addons]/esx_mechanicjob/fxmanifest.lua +++ b/server-data/resources/[esx_addons]/esx_mechanicjob/fxmanifest.lua @@ -1,29 +1,29 @@ -fx_version 'adamant' +fx_version("adamant") -game 'gta5' +game("gta5") -description 'Allows players to RP as a mechanic (repair and modify vehicles)' -lua54 'yes' -version '1.0.1' +description("Allows players to RP as a mechanic (repair and modify vehicles)") +lua54("yes") +version("1.0.1") -shared_script '@es_extended/imports.lua' +shared_script("@es_extended/imports.lua") -client_scripts { - '@es_extended/locale.lua', - 'locales/*.lua', - 'config.lua', - 'client/main.lua' -} +client_scripts({ + "@es_extended/locale.lua", + "locales/*.lua", + "config.lua", + "client/main.lua", +}) -server_scripts { - '@es_extended/locale.lua', - 'locales/*.lua', - 'config.lua', - 'server/main.lua' -} +server_scripts({ + "@es_extended/locale.lua", + "locales/*.lua", + "config.lua", + "server/main.lua", +}) -dependencies { - 'es_extended', - 'esx_society', - 'esx_billing' -} +dependencies({ + "es_extended", + "esx_society", + "bpt_billing", +}) diff --git a/server-data/resources/[esx_addons]/esx_policejob/README.md b/server-data/resources/[esx_addons]/esx_policejob/README.md index 21a7a79bd..f8974f415 100644 --- a/server-data/resources/[esx_addons]/esx_policejob/README.md +++ b/server-data/resources/[esx_addons]/esx_policejob/README.md @@ -4,7 +4,6 @@ This resource for ESX adds police armories, vehicle garages and ability for cops ### Requirements * Auto mode - * [esx_billing](https://github.com/esx-framework/esx_billing) * [esx_vehicleshop](https://github.com/esx-framework/esx_vehicleshop) * Player management (boss actions and armory with buyable weapons) diff --git a/server-data/resources/[esx_addons]/esx_policejob/client/main.lua b/server-data/resources/[esx_addons]/esx_policejob/client/main.lua index 88072a59a..396b2b8ab 100644 --- a/server-data/resources/[esx_addons]/esx_policejob/client/main.lua +++ b/server-data/resources/[esx_addons]/esx_policejob/client/main.lua @@ -1,1826 +1,1603 @@ local CurrentActionData, handcuffTimer, dragStatus, blipsCops, currentTask, sex, action = {}, {}, {}, {}, {}, {}, {} -local HasAlreadyEnteredMarker, isDead, isHandcuffed, hasAlreadyJoined, playerInService = - false, false, false, false, false +local HasAlreadyEnteredMarker, isDead, isHandcuffed, hasAlreadyJoined, playerInService = false, false, false, false, false local LastStation, LastPart, LastPartNum, LastEntity, CurrentAction, CurrentActionMsg dragStatus.isDragged, isInShopMenu = false, false function cleanPlayer(playerPed) - SetPedArmour(playerPed, 0) - ClearPedBloodDamage(playerPed) - ResetPedVisibleDamage(playerPed) - ClearPedLastWeaponDamage(playerPed) - ResetPedMovementClipset(playerPed, 0) + SetPedArmour(playerPed, 0) + ClearPedBloodDamage(playerPed) + ResetPedVisibleDamage(playerPed) + ClearPedLastWeaponDamage(playerPed) + ResetPedMovementClipset(playerPed, 0) end function setUniform(uniform, playerPed) - TriggerEvent("skinchanger:getSkin", function(skin) - local uniformObject + TriggerEvent("skinchanger:getSkin", function(skin) + local uniformObject - sex = (skin.sex == 0) and "male" or "female" + sex = (skin.sex == 0) and "male" or "female" - uniformObject = Config.Uniforms[uniform][sex] + uniformObject = Config.Uniforms[uniform][sex] - if uniformObject then - TriggerEvent("skinchanger:loadClothes", skin, uniformObject) + if uniformObject then + TriggerEvent("skinchanger:loadClothes", skin, uniformObject) - if uniform == "bullet_wear" then - SetPedArmour(playerPed, 100) - end - else - ESX.ShowNotification(TranslateCap("no_outfit")) - end - end) + if uniform == "bullet_wear" then + SetPedArmour(playerPed, 100) + end + else + ESX.ShowNotification(TranslateCap("no_outfit")) + end + end) end function OpenCloakroomMenu() - local playerPed = PlayerPedId() - local grade = ESX.PlayerData.job.grade_name - - local elements = { - { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom") }, - { icon = "fas fa-shirt", title = TranslateCap("citizen_wear"), value = "citizen_wear" }, - { icon = "fas fa-shirt", title = TranslateCap("bullet_wear"), uniform = "bullet_wear" }, - { icon = "fas fa-shirt", title = TranslateCap("gilet_wear"), uniform = "gilet_wear" }, - { icon = "fas fa-shirt", title = TranslateCap("police_wear"), uniform = grade }, - } - - if Config.EnableCustomPeds then - for _, v in ipairs(Config.CustomPeds.shared) do - elements[#elements + 1] = { - icon = "fas fa-shirt", - title = v.label, - value = "freemode_ped", - maleModel = v.maleModel, - femaleModel = v.femaleModel, - } - end - - for _, v in ipairs(Config.CustomPeds[grade]) do - elements[#elements + 1] = { - icon = "fas fa-shirt", - title = v.label, - value = "freemode_ped", - maleModel = v.maleModel, - femaleModel = v.femaleModel, - } - end - end - - ESX.OpenContext("right", elements, function(menu, element) - cleanPlayer(playerPed) - local data = { current = element } - - if data.current.value == "citizen_wear" then - if Config.EnableCustomPeds then - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) - local isMale = skin.sex == 0 - - TriggerEvent("skinchanger:loadDefaultModel", isMale, function() - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - TriggerEvent("esx:restoreLoadout") - end) - end) - end) - else - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) - TriggerEvent("skinchanger:loadSkin", skin) - end) - end - - if Config.EnableESXService then - ESX.TriggerServerCallback("esx_service:isInService", function(isInService) - if isInService then - playerInService = false - - local notification = { - title = TranslateCap("service_anonunce"), - subject = "", - msg = TranslateCap("service_out_announce", GetPlayerName(PlayerId())), - iconType = 1, - } - - TriggerServerEvent("esx_service:notifyAllInService", notification, "police") - - TriggerServerEvent("esx_service:disableService", "police") - TriggerEvent("esx_policejob:updateBlip") - ESX.ShowNotification(TranslateCap("service_out")) - end - end, "police") - end - end - - if Config.EnableESXService and data.current.value ~= "citizen_wear" then - local awaitService - - ESX.TriggerServerCallback("esx_service:isInService", function(isInService) - if not isInService then - if Config.MaxInService ~= -1 then - ESX.TriggerServerCallback( - "esx_service:enableService", - function(canTakeService, maxInService, inServiceCount) - if not canTakeService then - ESX.ShowNotification(TranslateCap("service_max", inServiceCount, maxInService)) - else - awaitService = true - playerInService = true - - local notification = { - title = TranslateCap("service_anonunce"), - subject = "", - msg = TranslateCap("service_in_announce", GetPlayerName(PlayerId())), - iconType = 1, - } - - TriggerServerEvent("esx_service:notifyAllInService", notification, "police") - TriggerEvent("esx_policejob:updateBlip") - ESX.ShowNotification(TranslateCap("service_in")) - end - end, - "police" - ) - else - awaitService = true - playerInService = true - - local notification = { - title = TranslateCap("service_anonunce"), - subject = "", - msg = TranslateCap("service_in_announce", GetPlayerName(PlayerId())), - iconType = 1, - } - - TriggerServerEvent("esx_service:notifyAllInService", notification, "police") - TriggerEvent("esx_policejob:updateBlip") - ESX.ShowNotification(TranslateCap("service_in")) - end - else - awaitService = true - end - end, "police") - - while awaitService == nil do - Wait(0) - end - - -- if we couldn't enter service don't let the player get changed - if not awaitService then - return - end - end - - if data.current.uniform then - setUniform(data.current.uniform, playerPed) - elseif data.current.value == "freemode_ped" then - local modelHash - - ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) - if skin.sex == 0 then - modelHash = joaat(data.current.maleModel) - else - modelHash = joaat(data.current.femaleModel) - end - - ESX.Streaming.RequestModel(modelHash, function() - SetPlayerModel(PlayerId(), modelHash) - SetModelAsNoLongerNeeded(modelHash) - SetPedDefaultComponentVariation(PlayerPedId()) - - TriggerEvent("esx:restoreLoadout") - end) - end) - end - end, function(menu) - CurrentAction = "menu_cloakroom" - CurrentActionMsg = TranslateCap("open_cloackroom") - CurrentActionData = {} - end) + local playerPed = PlayerPedId() + local grade = ESX.PlayerData.job.grade_name + + local elements = { + { unselectable = true, icon = "fas fa-shirt", title = TranslateCap("cloakroom") }, + { icon = "fas fa-shirt", title = TranslateCap("citizen_wear"), value = "citizen_wear" }, + { icon = "fas fa-shirt", title = TranslateCap("bullet_wear"), uniform = "bullet_wear" }, + { icon = "fas fa-shirt", title = TranslateCap("gilet_wear"), uniform = "gilet_wear" }, + { icon = "fas fa-shirt", title = TranslateCap("police_wear"), uniform = grade }, + } + + if Config.EnableCustomPeds then + for _, v in ipairs(Config.CustomPeds.shared) do + elements[#elements + 1] = { + icon = "fas fa-shirt", + title = v.label, + value = "freemode_ped", + maleModel = v.maleModel, + femaleModel = v.femaleModel, + } + end + + for _, v in ipairs(Config.CustomPeds[grade]) do + elements[#elements + 1] = { + icon = "fas fa-shirt", + title = v.label, + value = "freemode_ped", + maleModel = v.maleModel, + femaleModel = v.femaleModel, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + cleanPlayer(playerPed) + local data = { current = element } + + if data.current.value == "citizen_wear" then + if Config.EnableCustomPeds then + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) + local isMale = skin.sex == 0 + + TriggerEvent("skinchanger:loadDefaultModel", isMale, function() + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + TriggerEvent("esx:restoreLoadout") + end) + end) + end) + else + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin) + TriggerEvent("skinchanger:loadSkin", skin) + end) + end + + if Config.EnableESXService then + ESX.TriggerServerCallback("esx_service:isInService", function(isInService) + if isInService then + playerInService = false + + local notification = { + title = TranslateCap("service_anonunce"), + subject = "", + msg = TranslateCap("service_out_announce", GetPlayerName(PlayerId())), + iconType = 1, + } + + TriggerServerEvent("esx_service:notifyAllInService", notification, "police") + + TriggerServerEvent("esx_service:disableService", "police") + TriggerEvent("esx_policejob:updateBlip") + ESX.ShowNotification(TranslateCap("service_out")) + end + end, "police") + end + end + + if Config.EnableESXService and data.current.value ~= "citizen_wear" then + local awaitService + + ESX.TriggerServerCallback("esx_service:isInService", function(isInService) + if not isInService then + if Config.MaxInService ~= -1 then + ESX.TriggerServerCallback("esx_service:enableService", function(canTakeService, maxInService, inServiceCount) + if not canTakeService then + ESX.ShowNotification(TranslateCap("service_max", inServiceCount, maxInService)) + else + awaitService = true + playerInService = true + + local notification = { + title = TranslateCap("service_anonunce"), + subject = "", + msg = TranslateCap("service_in_announce", GetPlayerName(PlayerId())), + iconType = 1, + } + + TriggerServerEvent("esx_service:notifyAllInService", notification, "police") + TriggerEvent("esx_policejob:updateBlip") + ESX.ShowNotification(TranslateCap("service_in")) + end + end, "police") + else + awaitService = true + playerInService = true + + local notification = { + title = TranslateCap("service_anonunce"), + subject = "", + msg = TranslateCap("service_in_announce", GetPlayerName(PlayerId())), + iconType = 1, + } + + TriggerServerEvent("esx_service:notifyAllInService", notification, "police") + TriggerEvent("esx_policejob:updateBlip") + ESX.ShowNotification(TranslateCap("service_in")) + end + else + awaitService = true + end + end, "police") + + while awaitService == nil do + Wait(0) + end + + -- if we couldn't enter service don't let the player get changed + if not awaitService then + return + end + end + + if data.current.uniform then + setUniform(data.current.uniform, playerPed) + elseif data.current.value == "freemode_ped" then + local modelHash + + ESX.TriggerServerCallback("esx_skin:getPlayerSkin", function(skin, jobSkin) + if skin.sex == 0 then + modelHash = joaat(data.current.maleModel) + else + modelHash = joaat(data.current.femaleModel) + end + + ESX.Streaming.RequestModel(modelHash, function() + SetPlayerModel(PlayerId(), modelHash) + SetModelAsNoLongerNeeded(modelHash) + SetPedDefaultComponentVariation(PlayerPedId()) + + TriggerEvent("esx:restoreLoadout") + end) + end) + end + end, function(menu) + CurrentAction = "menu_cloakroom" + CurrentActionMsg = TranslateCap("open_cloackroom") + CurrentActionData = {} + end) end function OpenArmoryMenu(station) - local elements - if Config.OxInventory then - exports.ox_inventory:openInventory("stash", { id = "society_police", owner = station }) - return ESX.CloseContext() - else - elements = { - { unselectable = true, icon = "fas fa-gun", title = TranslateCap("armory") }, - { icon = "fas fa-gun", title = TranslateCap("buy_weapons"), value = "buy_weapons" }, - } - - if Config.EnableArmoryManagement then - table.insert(elements, { icon = "fas fa-gun", title = TranslateCap("get_weapon"), value = "get_weapon" }) - table.insert(elements, { icon = "fas fa-gun", title = TranslateCap("put_weapon"), value = "put_weapon" }) - table.insert(elements, { icon = "fas fa-box", title = TranslateCap("remove_object"), value = "get_stock" }) - table.insert(elements, { icon = "fas fa-box", title = TranslateCap("deposit_object"), value = "put_stock" }) - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - if data.current.value == "get_weapon" then - OpenGetWeaponMenu() - elseif data.current.value == "put_weapon" then - OpenPutWeaponMenu() - elseif data.current.value == "buy_weapons" then - OpenBuyWeaponsMenu() - elseif data.current.value == "put_stock" then - OpenPutStocksMenu() - elseif data.current.value == "get_stock" then - OpenGetStocksMenu() - end - end, function(menu) - CurrentAction = "menu_armory" - CurrentActionMsg = TranslateCap("open_armory") - CurrentActionData = { station = station } - end) + local elements + if Config.OxInventory then + exports.ox_inventory:openInventory("stash", { id = "society_police", owner = station }) + return ESX.CloseContext() + else + elements = { + { unselectable = true, icon = "fas fa-gun", title = TranslateCap("armory") }, + { icon = "fas fa-gun", title = TranslateCap("buy_weapons"), value = "buy_weapons" }, + } + + if Config.EnableArmoryManagement then + table.insert(elements, { icon = "fas fa-gun", title = TranslateCap("get_weapon"), value = "get_weapon" }) + table.insert(elements, { icon = "fas fa-gun", title = TranslateCap("put_weapon"), value = "put_weapon" }) + table.insert(elements, { icon = "fas fa-box", title = TranslateCap("remove_object"), value = "get_stock" }) + table.insert(elements, { icon = "fas fa-box", title = TranslateCap("deposit_object"), value = "put_stock" }) + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + if data.current.value == "get_weapon" then + OpenGetWeaponMenu() + elseif data.current.value == "put_weapon" then + OpenPutWeaponMenu() + elseif data.current.value == "buy_weapons" then + OpenBuyWeaponsMenu() + elseif data.current.value == "put_stock" then + OpenPutStocksMenu() + elseif data.current.value == "get_stock" then + OpenGetStocksMenu() + end + end, function(menu) + CurrentAction = "menu_armory" + CurrentActionMsg = TranslateCap("open_armory") + CurrentActionData = { station = station } + end) end function OpenPoliceActionsMenu() - local elements = { - { unselectable = true, icon = "fas fa-police", title = TranslateCap("menu_title") }, - { icon = "fas fa-user", title = TranslateCap("citizen_interaction"), value = "citizen_interaction" }, - { icon = "fas fa-car", title = TranslateCap("vehicle_interaction"), value = "vehicle_interaction" }, - { icon = "fas fa-object", title = TranslateCap("object_spawner"), value = "object_spawner" }, - } - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - - if data.current.value == "citizen_interaction" then - local elements2 = { - { unselectable = true, icon = "fas fa-user", title = element.title }, - { icon = "fas fa-idkyet", title = TranslateCap("id_card"), value = "identity_card" }, - { icon = "fas fa-idkyet", title = TranslateCap("search"), value = "search" }, - { icon = "fas fa-idkyet", title = TranslateCap("handcuff"), value = "handcuff" }, - { icon = "fas fa-idkyet", title = TranslateCap("drag"), value = "drag" }, - { icon = "fas fa-idkyet", title = TranslateCap("put_in_vehicle"), value = "put_in_vehicle" }, - { icon = "fas fa-idkyet", title = TranslateCap("out_the_vehicle"), value = "out_the_vehicle" }, - { icon = "fas fa-idkyet", title = TranslateCap("fine"), value = "fine" }, - { icon = "fas fa-idkyet", title = TranslateCap("unpaid_bills"), value = "unpaid_bills" }, - } - - if Config.EnableLicenses then - elements2[#elements2 + 1] = { - icon = "fas fa-scroll", - title = TranslateCap("license_check"), - value = "license", - } - end - - ESX.OpenContext("right", elements2, function(menu2, element2) - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer ~= -1 and closestDistance <= 3.0 then - local data2 = { current = element2 } - local action = data2.current.value - - if action == "identity_card" then - OpenIdentityCardMenu(closestPlayer) - elseif action == "search" then - OpenBodySearchMenu(closestPlayer) - elseif action == "handcuff" then - TriggerServerEvent("esx_policejob:handcuff", GetPlayerServerId(closestPlayer)) - elseif action == "drag" then - TriggerServerEvent("esx_policejob:drag", GetPlayerServerId(closestPlayer)) - elseif action == "put_in_vehicle" then - TriggerServerEvent("esx_policejob:putInVehicle", GetPlayerServerId(closestPlayer)) - elseif action == "out_the_vehicle" then - TriggerServerEvent("esx_policejob:OutVehicle", GetPlayerServerId(closestPlayer)) - elseif action == "fine" then - OpenFineMenu(closestPlayer) - elseif action == "license" then - ShowPlayerLicense(closestPlayer) - elseif action == "unpaid_bills" then - OpenUnpaidBillsMenu(closestPlayer) - end - else - ESX.ShowNotification(TranslateCap("no_players_nearby")) - end - end, function(menu) - OpenPoliceActionsMenu() - end) - elseif data.current.value == "vehicle_interaction" then - local elements3 = { - { unselectable = true, icon = "fas fa-car", title = element.title }, - } - local playerPed = PlayerPedId() - local vehicle = ESX.Game.GetVehicleInDirection() - - if DoesEntityExist(vehicle) then - elements3[#elements3 + 1] = - { icon = "fas fa-car", title = TranslateCap("vehicle_info"), value = "vehicle_infos" } - elements3[#elements3 + 1] = - { icon = "fas fa-car", title = TranslateCap("pick_lock"), value = "hijack_vehicle" } - elements3[#elements3 + 1] = { icon = "fas fa-car", title = TranslateCap("impound"), value = "impound" } - end - - elements3[#elements3 + 1] = { - icon = "fas fa-scroll", - title = TranslateCap("search_database"), - value = "search_database", - } - - ESX.OpenContext("right", elements3, function(menu3, element3) - local data2 = { current = element3 } - local coords = GetEntityCoords(playerPed) - vehicle = ESX.Game.GetVehicleInDirection() - action = data2.current.value - - if action == "search_database" then - LookupVehicle(element3) - elseif DoesEntityExist(vehicle) then - if action == "vehicle_infos" then - local vehicleData = ESX.Game.GetVehicleProperties(vehicle) - OpenVehicleInfosMenu(vehicleData) - elseif action == "hijack_vehicle" then - if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 3.0) then - TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_WELDING", 0, true) - Wait(20000) - ClearPedTasksImmediately(playerPed) - - SetVehicleDoorsLocked(vehicle, 1) - SetVehicleDoorsLockedForAllPlayers(vehicle, false) - ESX.ShowNotification(TranslateCap("vehicle_unlocked")) - end - elseif action == "impound" then - if currentTask.busy then - return - end - - ESX.ShowHelpNotification(TranslateCap("impound_prompt")) - TaskStartScenarioInPlace(playerPed, "CODE_HUMAN_MEDIC_TEND_TO_DEAD", 0, true) - - currentTask.busy = true - currentTask.task = ESX.SetTimeout(10000, function() - ClearPedTasks(playerPed) - ImpoundVehicle(vehicle) - Wait(100) - end) - - CreateThread(function() - while currentTask.busy do - Wait(1000) - - vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71) - if not DoesEntityExist(vehicle) and currentTask.busy then - ESX.ShowNotification(TranslateCap("impound_canceled_moved")) - ESX.ClearTimeout(currentTask.task) - ClearPedTasks(playerPed) - currentTask.busy = false - break - end - end - end) - end - else - ESX.ShowNotification(TranslateCap("no_vehicles_nearby")) - end - end, function(menu) - OpenPoliceActionsMenu() - end) - elseif data.current.value == "object_spawner" then - local elements4 = { - { unselectable = true, icon = "fas fa-object", title = element.title }, - { icon = "fas fa-cone", title = TranslateCap("cone"), model = "prop_roadcone02a" }, - { icon = "fas fa-cone", title = TranslateCap("barrier"), model = "prop_barrier_work05" }, - { icon = "fas fa-cone", title = TranslateCap("spikestrips"), model = "p_ld_stinger_s" }, - { icon = "fas fa-cone", title = TranslateCap("box"), model = "prop_boxpile_07d" }, - { icon = "fas fa-cone", title = TranslateCap("cash"), model = "hei_prop_cash_crate_half_full" }, - } - - ESX.OpenContext("right", elements4, function(menu4, element4) - local data2 = { current = element4 } - local playerPed = PlayerPedId() - local coords, forward = GetEntityCoords(playerPed), GetEntityForwardVector(playerPed) - local objectCoords = (coords + forward * 1.0) - - ESX.Game.SpawnObject(data2.current.model, objectCoords, function(obj) - Wait(100) - SetEntityHeading(obj, GetEntityHeading(playerPed)) - PlaceObjectOnGroundProperly(obj) - end) - end, function(menu) - OpenPoliceActionsMenu() - end) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-police", title = TranslateCap("menu_title") }, + { icon = "fas fa-user", title = TranslateCap("citizen_interaction"), value = "citizen_interaction" }, + { icon = "fas fa-car", title = TranslateCap("vehicle_interaction"), value = "vehicle_interaction" }, + { icon = "fas fa-object", title = TranslateCap("object_spawner"), value = "object_spawner" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + + if data.current.value == "citizen_interaction" then + local elements2 = { + { unselectable = true, icon = "fas fa-user", title = element.title }, + { icon = "fas fa-idkyet", title = TranslateCap("id_card"), value = "identity_card" }, + { icon = "fas fa-idkyet", title = TranslateCap("search"), value = "search" }, + { icon = "fas fa-idkyet", title = TranslateCap("handcuff"), value = "handcuff" }, + { icon = "fas fa-idkyet", title = TranslateCap("drag"), value = "drag" }, + { icon = "fas fa-idkyet", title = TranslateCap("put_in_vehicle"), value = "put_in_vehicle" }, + { icon = "fas fa-idkyet", title = TranslateCap("out_the_vehicle"), value = "out_the_vehicle" }, + { icon = "fas fa-idkyet", title = TranslateCap("fine"), value = "fine" }, + { icon = "fas fa-idkyet", title = TranslateCap("unpaid_bills"), value = "unpaid_bills" }, + } + + if Config.EnableLicenses then + elements2[#elements2 + 1] = { + icon = "fas fa-scroll", + title = TranslateCap("license_check"), + value = "license", + } + end + + ESX.OpenContext("right", elements2, function(menu2, element2) + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer ~= -1 and closestDistance <= 3.0 then + local data2 = { current = element2 } + local action = data2.current.value + + if action == "identity_card" then + OpenIdentityCardMenu(closestPlayer) + elseif action == "search" then + OpenBodySearchMenu(closestPlayer) + elseif action == "handcuff" then + TriggerServerEvent("esx_policejob:handcuff", GetPlayerServerId(closestPlayer)) + elseif action == "drag" then + TriggerServerEvent("esx_policejob:drag", GetPlayerServerId(closestPlayer)) + elseif action == "put_in_vehicle" then + TriggerServerEvent("esx_policejob:putInVehicle", GetPlayerServerId(closestPlayer)) + elseif action == "out_the_vehicle" then + TriggerServerEvent("esx_policejob:OutVehicle", GetPlayerServerId(closestPlayer)) + elseif action == "fine" then + OpenFineMenu(closestPlayer) + elseif action == "license" then + ShowPlayerLicense(closestPlayer) + elseif action == "unpaid_bills" then + OpenUnpaidBillsMenu(closestPlayer) + end + else + ESX.ShowNotification(TranslateCap("no_players_nearby")) + end + end, function(menu) + OpenPoliceActionsMenu() + end) + elseif data.current.value == "vehicle_interaction" then + local elements3 = { + { unselectable = true, icon = "fas fa-car", title = element.title }, + } + local playerPed = PlayerPedId() + local vehicle = ESX.Game.GetVehicleInDirection() + + if DoesEntityExist(vehicle) then + elements3[#elements3 + 1] = { icon = "fas fa-car", title = TranslateCap("vehicle_info"), value = "vehicle_infos" } + elements3[#elements3 + 1] = { icon = "fas fa-car", title = TranslateCap("pick_lock"), value = "hijack_vehicle" } + elements3[#elements3 + 1] = { icon = "fas fa-car", title = TranslateCap("impound"), value = "impound" } + end + + elements3[#elements3 + 1] = { + icon = "fas fa-scroll", + title = TranslateCap("search_database"), + value = "search_database", + } + + ESX.OpenContext("right", elements3, function(menu3, element3) + local data2 = { current = element3 } + local coords = GetEntityCoords(playerPed) + vehicle = ESX.Game.GetVehicleInDirection() + action = data2.current.value + + if action == "search_database" then + LookupVehicle(element3) + elseif DoesEntityExist(vehicle) then + if action == "vehicle_infos" then + local vehicleData = ESX.Game.GetVehicleProperties(vehicle) + OpenVehicleInfosMenu(vehicleData) + elseif action == "hijack_vehicle" then + if IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 3.0) then + TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_WELDING", 0, true) + Wait(20000) + ClearPedTasksImmediately(playerPed) + + SetVehicleDoorsLocked(vehicle, 1) + SetVehicleDoorsLockedForAllPlayers(vehicle, false) + ESX.ShowNotification(TranslateCap("vehicle_unlocked")) + end + elseif action == "impound" then + if currentTask.busy then + return + end + + ESX.ShowHelpNotification(TranslateCap("impound_prompt")) + TaskStartScenarioInPlace(playerPed, "CODE_HUMAN_MEDIC_TEND_TO_DEAD", 0, true) + + currentTask.busy = true + currentTask.task = ESX.SetTimeout(10000, function() + ClearPedTasks(playerPed) + ImpoundVehicle(vehicle) + Wait(100) + end) + + CreateThread(function() + while currentTask.busy do + Wait(1000) + + vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71) + if not DoesEntityExist(vehicle) and currentTask.busy then + ESX.ShowNotification(TranslateCap("impound_canceled_moved")) + ESX.ClearTimeout(currentTask.task) + ClearPedTasks(playerPed) + currentTask.busy = false + break + end + end + end) + end + else + ESX.ShowNotification(TranslateCap("no_vehicles_nearby")) + end + end, function(menu) + OpenPoliceActionsMenu() + end) + elseif data.current.value == "object_spawner" then + local elements4 = { + { unselectable = true, icon = "fas fa-object", title = element.title }, + { icon = "fas fa-cone", title = TranslateCap("cone"), model = "prop_roadcone02a" }, + { icon = "fas fa-cone", title = TranslateCap("barrier"), model = "prop_barrier_work05" }, + { icon = "fas fa-cone", title = TranslateCap("spikestrips"), model = "p_ld_stinger_s" }, + { icon = "fas fa-cone", title = TranslateCap("box"), model = "prop_boxpile_07d" }, + { icon = "fas fa-cone", title = TranslateCap("cash"), model = "hei_prop_cash_crate_half_full" }, + } + + ESX.OpenContext("right", elements4, function(menu4, element4) + local data2 = { current = element4 } + local playerPed = PlayerPedId() + local coords, forward = GetEntityCoords(playerPed), GetEntityForwardVector(playerPed) + local objectCoords = (coords + forward * 1.0) + + ESX.Game.SpawnObject(data2.current.model, objectCoords, function(obj) + Wait(100) + SetEntityHeading(obj, GetEntityHeading(playerPed)) + PlaceObjectOnGroundProperly(obj) + end) + end, function(menu) + OpenPoliceActionsMenu() + end) + end + end) end function OpenIdentityCardMenu(player) - ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(data) - local elements = { - { icon = "fas fa-user", title = TranslateCap("name", data.name) }, - { icon = "fas fa-user", title = TranslateCap("job", ("%s - %s"):format(data.job, data.grade)) }, - } - - if Config.EnableESXIdentity then - elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("sex", TranslateCap(data.sex)) } - elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("sex", TranslateCap(data.sex)) } - elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("height", data.height) } - end - - if Config.EnableESXOptionalneeds and data.drunk then - elements[#elements + 1] = { title = TranslateCap("bac", data.drunk) } - end - - if data.licenses then - elements[#elements + 1] = { title = TranslateCap("license_label") } - - for i = 1, #data.licenses, 1 do - elements[#elements + 1] = { title = data.licenses[i].label } - end - end - - ESX.OpenContext("right", elements, nil, function(menu) - OpenPoliceActionsMenu() - end) - end, GetPlayerServerId(player)) + ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(data) + local elements = { + { icon = "fas fa-user", title = TranslateCap("name", data.name) }, + { icon = "fas fa-user", title = TranslateCap("job", ("%s - %s"):format(data.job, data.grade)) }, + } + + if Config.EnableESXIdentity then + elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("sex", TranslateCap(data.sex)) } + elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("sex", TranslateCap(data.sex)) } + elements[#elements + 1] = { icon = "fas fa-user", title = TranslateCap("height", data.height) } + end + + if Config.EnableESXOptionalneeds and data.drunk then + elements[#elements + 1] = { title = TranslateCap("bac", data.drunk) } + end + + if data.licenses then + elements[#elements + 1] = { title = TranslateCap("license_label") } + + for i = 1, #data.licenses, 1 do + elements[#elements + 1] = { title = data.licenses[i].label } + end + end + + ESX.OpenContext("right", elements, nil, function(menu) + OpenPoliceActionsMenu() + end) + end, GetPlayerServerId(player)) end function OpenBodySearchMenu(player) - if Config.OxInventory then - ESX.CloseContext() - exports.ox_inventory:openInventory("player", GetPlayerServerId(player)) - return - end - - ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(data) - local elements = { - { unselectable = true, icon = "fas fa-user", title = TranslateCap("search") }, - } - - for i = 1, #data.accounts, 1 do - if data.accounts[i].name == "black_money" and data.accounts[i].money > 0 then - elements[#elements + 1] = { - icon = "fas fa-money", - title = TranslateCap("confiscate_dirty", ESX.Math.Round(data.accounts[i].money)), - value = "black_money", - itemType = "item_account", - amount = data.accounts[i].money, - } - break - end - end - - table.insert(elements, { label = TranslateCap("guns_label") }) - - for i = 1, #data.weapons, 1 do - elements[#elements + 1] = { - icon = "fas fa-gun", - title = TranslateCap( - "confiscate_weapon", - ESX.GetWeaponLabel(data.weapons[i].name), - data.weapons[i].ammo - ), - value = data.weapons[i].name, - itemType = "item_weapon", - amount = data.weapons[i].ammo, - } - end - - elements[#elements + 1] = { title = TranslateCap("inventory_label") } - - for i = 1, #data.inventory, 1 do - if data.inventory[i].count > 0 then - elements[#elements + 1] = { - icon = "fas fa-box", - title = TranslateCap("confiscate_inv", data.inventory[i].count, data.inventory[i].label), - value = data.inventory[i].name, - itemType = "item_standard", - amount = data.inventory[i].count, - } - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - if data.current.value then - TriggerServerEvent( - "esx_policejob:confiscatePlayerItem", - GetPlayerServerId(player), - data.current.itemType, - data.current.value, - data.current.amount - ) - OpenBodySearchMenu(player) - end - end) - end, GetPlayerServerId(player)) + if Config.OxInventory then + ESX.CloseContext() + exports.ox_inventory:openInventory("player", GetPlayerServerId(player)) + return + end + + ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(data) + local elements = { + { unselectable = true, icon = "fas fa-user", title = TranslateCap("search") }, + } + + for i = 1, #data.accounts, 1 do + if data.accounts[i].name == "black_money" and data.accounts[i].money > 0 then + elements[#elements + 1] = { + icon = "fas fa-money", + title = TranslateCap("confiscate_dirty", ESX.Math.Round(data.accounts[i].money)), + value = "black_money", + itemType = "item_account", + amount = data.accounts[i].money, + } + break + end + end + + table.insert(elements, { label = TranslateCap("guns_label") }) + + for i = 1, #data.weapons, 1 do + elements[#elements + 1] = { + icon = "fas fa-gun", + title = TranslateCap("confiscate_weapon", ESX.GetWeaponLabel(data.weapons[i].name), data.weapons[i].ammo), + value = data.weapons[i].name, + itemType = "item_weapon", + amount = data.weapons[i].ammo, + } + end + + elements[#elements + 1] = { title = TranslateCap("inventory_label") } + + for i = 1, #data.inventory, 1 do + if data.inventory[i].count > 0 then + elements[#elements + 1] = { + icon = "fas fa-box", + title = TranslateCap("confiscate_inv", data.inventory[i].count, data.inventory[i].label), + value = data.inventory[i].name, + itemType = "item_standard", + amount = data.inventory[i].count, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + if data.current.value then + TriggerServerEvent("esx_policejob:confiscatePlayerItem", GetPlayerServerId(player), data.current.itemType, data.current.value, data.current.amount) + OpenBodySearchMenu(player) + end + end) + end, GetPlayerServerId(player)) end function OpenFineMenu(player) - if Config.EnableFinePresets then - local elements = { - { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("fine") }, - { icon = "fas fa-scroll", title = TranslateCap("traffic_offense"), value = 0 }, - { icon = "fas fa-scroll", title = TranslateCap("minor_offense"), value = 1 }, - { icon = "fas fa-scroll", title = TranslateCap("average_offense"), value = 2 }, - { icon = "fas fa-scroll", title = TranslateCap("major_offense"), value = 3 }, - } - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - OpenFineCategoryMenu(player, data.current.value) - end) - else - ESX.CloseContext() - ESX.CloseContext() - OpenFineTextInput(player) - end + if Config.EnableFinePresets then + local elements = { + { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("fine") }, + { icon = "fas fa-scroll", title = TranslateCap("traffic_offense"), value = 0 }, + { icon = "fas fa-scroll", title = TranslateCap("minor_offense"), value = 1 }, + { icon = "fas fa-scroll", title = TranslateCap("average_offense"), value = 2 }, + { icon = "fas fa-scroll", title = TranslateCap("major_offense"), value = 3 }, + } + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + OpenFineCategoryMenu(player, data.current.value) + end) + else + ESX.CloseContext() + ESX.CloseContext() + OpenFineTextInput(player) + end end local fineList = {} function OpenFineCategoryMenu(player, category) - if not fineList[category] then - local p = promise.new() - - ESX.TriggerServerCallback("esx_policejob:getFineList", function(fines) - p:resolve(fines) - end, category) - - fineList[category] = Citizen.Await(p) - end - - local elements = { - { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("fine") }, - } - - for k, fine in ipairs(fineList[category]) do - elements[#elements + 1] = { - icon = "fas fa-scroll", - title = ('%s %s'):format( - fine.label, - TranslateCap("armory_item", ESX.Math.GroupDigits(fine.amount)) - ), - value = fine.id, - amount = fine.amount, - fineLabel = fine.label, - } - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - if Config.EnablePlayerManagement then - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(player), - "society_police", - TranslateCap("fine_total", data.current.fineLabel), - data.current.amount - ) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(player), - "", - TranslateCap("fine_total", data.current.fineLabel), - data.current.amount - ) - end - - ESX.SetTimeout(300, function() - OpenFineCategoryMenu(player, category) - end) - end) + if not fineList[category] then + local p = promise.new() + + ESX.TriggerServerCallback("esx_policejob:getFineList", function(fines) + p:resolve(fines) + end, category) + + fineList[category] = Citizen.Await(p) + end + + local elements = { + { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("fine") }, + } + + for k, fine in ipairs(fineList[category]) do + elements[#elements + 1] = { + icon = "fas fa-scroll", + title = ('%s %s'):format(fine.label, TranslateCap("armory_item", ESX.Math.GroupDigits(fine.amount))), + value = fine.id, + amount = fine.amount, + fineLabel = fine.label, + } + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + if Config.EnablePlayerManagement then + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(player), "society_police", TranslateCap("fine_total", data.current.fineLabel), data.current.amount) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(player), "", TranslateCap("fine_total", data.current.fineLabel), data.current.amount) + end + + ESX.SetTimeout(300, function() + OpenFineCategoryMenu(player, category) + end) + end) end function OpenFineTextInput(player) - Citizen.CreateThread(function() - local amount = 0 - local reason = "" - AddTextEntry("FMMC_KEY_TIP1", TranslateCap("fine_enter_amount")) - Citizen.Wait(0) - DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP1", "", "", "", "", "", 30) - while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do - Citizen.Wait(0) - end - if UpdateOnscreenKeyboard() ~= 2 then - amount = tonumber(GetOnscreenKeyboardResult()) - if amount == nil or amount <= 0 then - ESX.ShowNotification(TranslateCap("invalid_amount")) - return - end - end - AddTextEntry("FMMC_KEY_TIP1", TranslateCap("fine_enter_text")) - Citizen.Wait(0) - DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP1", "", "", "", "", "", 120) - while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do - Citizen.Wait(0) - end - if UpdateOnscreenKeyboard() ~= 2 then - reason = GetOnscreenKeyboardResult() - end - Citizen.Wait(500) - TriggerServerEvent("esx_billing:sendBill", GetPlayerServerId(player), "society_police", reason, amount) - OpenPoliceActionsMenu() - end) + Citizen.CreateThread(function() + local amount = 0 + local reason = "" + AddTextEntry("FMMC_KEY_TIP1", TranslateCap("fine_enter_amount")) + Citizen.Wait(0) + DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP1", "", "", "", "", "", 30) + while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do + Citizen.Wait(0) + end + if UpdateOnscreenKeyboard() ~= 2 then + amount = tonumber(GetOnscreenKeyboardResult()) + if amount == nil or amount <= 0 then + ESX.ShowNotification(TranslateCap("invalid_amount")) + return + end + end + AddTextEntry("FMMC_KEY_TIP1", TranslateCap("fine_enter_text")) + Citizen.Wait(0) + DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP1", "", "", "", "", "", 120) + while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do + Citizen.Wait(0) + end + if UpdateOnscreenKeyboard() ~= 2 then + reason = GetOnscreenKeyboardResult() + end + Citizen.Wait(500) + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(player), "society_police", reason, amount) + OpenPoliceActionsMenu() + end) end function LookupVehicle(elementF) - local elements = { - { unselectable = true, icon = "fas fa-car", title = elementF.title }, - { title = TranslateCap("search_plate"), input = true, inputType = "text", inputPlaceholder = "ABC 123" }, - { icon = "fas fa-check-double", title = TranslateCap("lookup_plate"), value = "lookup" }, - } - - ESX.OpenContext("right", elements, function(menu, element) - local data = { value = menu.eles[2].inputValue } - local length = string.len(data.value) - if not data.value or length < 2 or length > 8 then - ESX.ShowNotification(TranslateCap("search_database_error_invalid")) - else - ESX.TriggerServerCallback("esx_policejob:getVehicleInfos", function(retrivedInfo) - local elements = { - { unselectable = true, icon = "fas fa-car", title = element.title }, - { unselectable = true, icon = "fas fa-car", title = TranslateCap("plate", retrivedInfo.plate) }, - } - - if not retrivedInfo.owner then - elements[#elements + 1] = - { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner_unknown") } - else - elements[#elements + 1] = - { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner", retrivedInfo.owner) } - end - - ESX.OpenContext("right", elements, nil, function(menu) - OpenPoliceActionsMenu() - end) - end, data.value) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-car", title = elementF.title }, + { title = TranslateCap("search_plate"), input = true, inputType = "text", inputPlaceholder = "ABC 123" }, + { icon = "fas fa-check-double", title = TranslateCap("lookup_plate"), value = "lookup" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + local data = { value = menu.eles[2].inputValue } + local length = string.len(data.value) + if not data.value or length < 2 or length > 8 then + ESX.ShowNotification(TranslateCap("search_database_error_invalid")) + else + ESX.TriggerServerCallback("esx_policejob:getVehicleInfos", function(retrivedInfo) + local elements = { + { unselectable = true, icon = "fas fa-car", title = element.title }, + { unselectable = true, icon = "fas fa-car", title = TranslateCap("plate", retrivedInfo.plate) }, + } + + if not retrivedInfo.owner then + elements[#elements + 1] = { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner_unknown") } + else + elements[#elements + 1] = { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner", retrivedInfo.owner) } + end + + ESX.OpenContext("right", elements, nil, function(menu) + OpenPoliceActionsMenu() + end) + end, data.value) + end + end) end function ShowPlayerLicense(player) - local elements = { - { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("license_revoke") }, - } - - ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(playerData) - if playerData.licenses then - for i = 1, #playerData.licenses, 1 do - if playerData.licenses[i].label and playerData.licenses[i].type then - elements[#elements + 1] = { - icon = "fas fa-scroll", - title = playerData.licenses[i].label, - type = playerData.licenses[i].type, - } - end - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - ESX.ShowNotification(TranslateCap("licence_you_revoked", data.current.label, playerData.name)) - TriggerServerEvent( - "esx_policejob:message", - GetPlayerServerId(player), - TranslateCap("license_revoked", data.current.label) - ) - - TriggerServerEvent("esx_license:removeLicense", GetPlayerServerId(player), data.current.type) - - ESX.SetTimeout(300, function() - ShowPlayerLicense(player) - end) - end) - end, GetPlayerServerId(player)) + local elements = { + { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("license_revoke") }, + } + + ESX.TriggerServerCallback("esx_policejob:getOtherPlayerData", function(playerData) + if playerData.licenses then + for i = 1, #playerData.licenses, 1 do + if playerData.licenses[i].label and playerData.licenses[i].type then + elements[#elements + 1] = { + icon = "fas fa-scroll", + title = playerData.licenses[i].label, + type = playerData.licenses[i].type, + } + end + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + ESX.ShowNotification(TranslateCap("licence_you_revoked", data.current.label, playerData.name)) + TriggerServerEvent("esx_policejob:message", GetPlayerServerId(player), TranslateCap("license_revoked", data.current.label)) + + TriggerServerEvent("esx_license:removeLicense", GetPlayerServerId(player), data.current.type) + + ESX.SetTimeout(300, function() + ShowPlayerLicense(player) + end) + end) + end, GetPlayerServerId(player)) end function OpenUnpaidBillsMenu(player) - local elements = { - { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("unpaid_bills") }, - } - - ESX.TriggerServerCallback("esx_billing:getTargetBills", function(bills) - for _, bill in ipairs(bills) do - elements[#elements + 1] = { - unselectable = true, - icon = "fas fa-scroll", - title = ('%s - %s'):format( - bill.label, - TranslateCap("armory_item", ESX.Math.GroupDigits(bill.amount)) - ), - billId = bill.id, - } - end - - ESX.OpenContext("right", elements, nil, nil) - end, GetPlayerServerId(player)) + local elements = { + { unselectable = true, icon = "fas fa-scroll", title = TranslateCap("unpaid_bills") }, + } + + ESX.TriggerServerCallback("bpt:getTargetBills", function(bills) + for _, bill in ipairs(bills) do + elements[#elements + 1] = { + unselectable = true, + icon = "fas fa-scroll", + title = ('%s - %s'):format(bill.label, TranslateCap("armory_item", ESX.Math.GroupDigits(bill.amount))), + billId = bill.id, + } + end + + ESX.OpenContext("right", elements, nil, nil) + end, GetPlayerServerId(player)) end function OpenVehicleInfosMenu(vehicleData) - ESX.TriggerServerCallback("esx_policejob:getVehicleInfos", function(retrivedInfo) - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("vehicle_info") }, - { icon = "fas fa-car", title = TranslateCap("plate", retrivedInfo.plate) }, - } - - if not retrivedInfo.owner then - elements[#elements + 1] = - { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner_unknown") } - else - elements[#elements + 1] = - { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner", retrivedInfo.owner) } - end - - ESX.OpenContext("right", elements, nil, nil) - end, vehicleData.plate) + ESX.TriggerServerCallback("esx_policejob:getVehicleInfos", function(retrivedInfo) + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("vehicle_info") }, + { icon = "fas fa-car", title = TranslateCap("plate", retrivedInfo.plate) }, + } + + if not retrivedInfo.owner then + elements[#elements + 1] = { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner_unknown") } + else + elements[#elements + 1] = { unselectable = true, icon = "fas fa-user", title = TranslateCap("owner", retrivedInfo.owner) } + end + + ESX.OpenContext("right", elements, nil, nil) + end, vehicleData.plate) end function OpenGetWeaponMenu() - ESX.TriggerServerCallback("esx_policejob:getArmoryWeapons", function(weapons) - local elements = { - { unselectable = true, icon = "fas fa-gun", title = TranslateCap("get_weapon_menu") }, - } - - for i = 1, #weapons, 1 do - if weapons[i].count > 0 then - elements[#elements + 1] = { - icon = "fas fa-gun", - title = "x" .. weapons[i].count .. " " .. ESX.GetWeaponLabel(weapons[i].name), - value = weapons[i].name, - } - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - ESX.TriggerServerCallback("esx_policejob:removeArmoryWeapon", function() - ESX.CloseContext() - OpenGetWeaponMenu() - end, data.current.value) - end) - end) + ESX.TriggerServerCallback("esx_policejob:getArmoryWeapons", function(weapons) + local elements = { + { unselectable = true, icon = "fas fa-gun", title = TranslateCap("get_weapon_menu") }, + } + + for i = 1, #weapons, 1 do + if weapons[i].count > 0 then + elements[#elements + 1] = { + icon = "fas fa-gun", + title = "x" .. weapons[i].count .. " " .. ESX.GetWeaponLabel(weapons[i].name), + value = weapons[i].name, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + ESX.TriggerServerCallback("esx_policejob:removeArmoryWeapon", function() + ESX.CloseContext() + OpenGetWeaponMenu() + end, data.current.value) + end) + end) end function OpenPutWeaponMenu() - local elements = { - { unselectable = true, icon = "fas fa-gun", title = TranslateCap("put_weapon_menu") }, - } - local playerPed = PlayerPedId() - local weaponList = ESX.GetWeaponList() - - for i = 1, #weaponList, 1 do - local weaponHash = joaat(weaponList[i].name) - - if HasPedGotWeapon(playerPed, weaponHash, false) and weaponList[i].name ~= "WEAPON_UNARMED" then - elements[#elements + 1] = { - icon = "fas fa-gun", - title = weaponList[i].label, - value = weaponList[i].name, - } - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - ESX.TriggerServerCallback("esx_policejob:addArmoryWeapon", function() - ESX.CloseContext() - OpenPutWeaponMenu() - end, data.current.value, true) - end) + local elements = { + { unselectable = true, icon = "fas fa-gun", title = TranslateCap("put_weapon_menu") }, + } + local playerPed = PlayerPedId() + local weaponList = ESX.GetWeaponList() + + for i = 1, #weaponList, 1 do + local weaponHash = joaat(weaponList[i].name) + + if HasPedGotWeapon(playerPed, weaponHash, false) and weaponList[i].name ~= "WEAPON_UNARMED" then + elements[#elements + 1] = { + icon = "fas fa-gun", + title = weaponList[i].label, + value = weaponList[i].name, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + ESX.TriggerServerCallback("esx_policejob:addArmoryWeapon", function() + ESX.CloseContext() + OpenPutWeaponMenu() + end, data.current.value, true) + end) end function OpenBuyWeaponsMenu() - local elements = { - { unselectable = true, icon = "fas fa-gun", title = TranslateCap("armory_weapontitle") }, - } - local playerPed = PlayerPedId() - - for _, v in ipairs(Config.AuthorizedWeapons[ESX.PlayerData.job.grade_name]) do - local _, weapon = ESX.GetWeapon(v.weapon) - local components, label = {} - local hasWeapon = HasPedGotWeapon(playerPed, joaat(v.weapon), false) - - if v.components then - for i = 1, #v.components do - if v.components[i] then - local component = weapon.components[i] - local hasComponent = HasPedGotWeaponComponent(playerPed, joaat(v.weapon), component.hash) - - if hasComponent then - label = ('%s: %s'):format( - component.label, - TranslateCap("armory_owned") - ) - else - if v.components[i] > 0 then - label = ('%s: %s'):format( - component.label, - TranslateCap("armory_item", ESX.Math.GroupDigits(v.components[i])) - ) - else - label = ('%s: %s'):format( - component.label, - TranslateCap("armory_free") - ) - end - end - - components[#components + 1] = { - icon = "fas fa-gun", - title = label, - componentLabel = component.label, - hash = component.hash, - name = component.name, - price = v.components[i], - hasComponent = hasComponent, - componentNum = i, - } - end - end - end - - if hasWeapon and v.components then - label = ('%s: >'):format(weapon.label) - elseif hasWeapon and not v.components then - label = ('%s: %s'):format(weapon.label, TranslateCap("armory_owned")) - else - if v.price > 0 then - label = ('%s: %s'):format( - weapon.label, - TranslateCap("armory_item", ESX.Math.GroupDigits(v.price)) - ) - else - label = ('%s: %s'):format(weapon.label, TranslateCap("armory_free")) - end - end - - elements[#elements + 1] = { - icon = "fas fa-gun", - title = label, - weaponLabel = weapon.label, - name = weapon.name, - components = components, - price = v.price, - hasWeapon = hasWeapon, - } - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - if data.current.hasWeapon then - if #data.current.components > 0 then - OpenWeaponComponentShop(data.current.components, data.current.name, menu) - end - else - ESX.TriggerServerCallback("esx_policejob:buyWeapon", function(bought) - if bought then - if data.current.price > 0 then - ESX.ShowNotification( - TranslateCap( - "armory_bought", - data.current.weaponLabel, - ESX.Math.GroupDigits(data.current.price) - ) - ) - end - - ESX.CloseContext() - OpenBuyWeaponsMenu() - else - ESX.ShowNotification(TranslateCap("armory_money")) - end - end, data.current.name, 1) - end - end) + local elements = { + { unselectable = true, icon = "fas fa-gun", title = TranslateCap("armory_weapontitle") }, + } + local playerPed = PlayerPedId() + + for _, v in ipairs(Config.AuthorizedWeapons[ESX.PlayerData.job.grade_name]) do + local _, weapon = ESX.GetWeapon(v.weapon) + local components, label = {} + local hasWeapon = HasPedGotWeapon(playerPed, joaat(v.weapon), false) + + if v.components then + for i = 1, #v.components do + if v.components[i] then + local component = weapon.components[i] + local hasComponent = HasPedGotWeaponComponent(playerPed, joaat(v.weapon), component.hash) + + if hasComponent then + label = ('%s: %s'):format(component.label, TranslateCap("armory_owned")) + else + if v.components[i] > 0 then + label = ('%s: %s'):format(component.label, TranslateCap("armory_item", ESX.Math.GroupDigits(v.components[i]))) + else + label = ('%s: %s'):format(component.label, TranslateCap("armory_free")) + end + end + + components[#components + 1] = { + icon = "fas fa-gun", + title = label, + componentLabel = component.label, + hash = component.hash, + name = component.name, + price = v.components[i], + hasComponent = hasComponent, + componentNum = i, + } + end + end + end + + if hasWeapon and v.components then + label = ('%s: >'):format(weapon.label) + elseif hasWeapon and not v.components then + label = ('%s: %s'):format(weapon.label, TranslateCap("armory_owned")) + else + if v.price > 0 then + label = ('%s: %s'):format(weapon.label, TranslateCap("armory_item", ESX.Math.GroupDigits(v.price))) + else + label = ('%s: %s'):format(weapon.label, TranslateCap("armory_free")) + end + end + + elements[#elements + 1] = { + icon = "fas fa-gun", + title = label, + weaponLabel = weapon.label, + name = weapon.name, + components = components, + price = v.price, + hasWeapon = hasWeapon, + } + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + if data.current.hasWeapon then + if #data.current.components > 0 then + OpenWeaponComponentShop(data.current.components, data.current.name, menu) + end + else + ESX.TriggerServerCallback("esx_policejob:buyWeapon", function(bought) + if bought then + if data.current.price > 0 then + ESX.ShowNotification(TranslateCap("armory_bought", data.current.weaponLabel, ESX.Math.GroupDigits(data.current.price))) + end + + ESX.CloseContext() + OpenBuyWeaponsMenu() + else + ESX.ShowNotification(TranslateCap("armory_money")) + end + end, data.current.name, 1) + end + end) end function OpenWeaponComponentShop(components, weaponName, parentShop) - ESX.OpenContext("right", components, function(menu, element) - local data = { current = element } - if data.current.hasComponent then - ESX.ShowNotification(TranslateCap("armory_hascomponent")) - else - ESX.TriggerServerCallback("esx_policejob:buyWeapon", function(bought) - if bought then - if data.current.price > 0 then - ESX.ShowNotification( - TranslateCap( - "armory_bought", - data.current.componentLabel, - ESX.Math.GroupDigits(data.current.price) - ) - ) - end - - ESX.CloseContext() - parentShop.close() - OpenBuyWeaponsMenu() - else - ESX.ShowNotification(TranslateCap("armory_money")) - end - end, weaponName, 2, data.current.componentNum) - end - end) + ESX.OpenContext("right", components, function(menu, element) + local data = { current = element } + if data.current.hasComponent then + ESX.ShowNotification(TranslateCap("armory_hascomponent")) + else + ESX.TriggerServerCallback("esx_policejob:buyWeapon", function(bought) + if bought then + if data.current.price > 0 then + ESX.ShowNotification(TranslateCap("armory_bought", data.current.componentLabel, ESX.Math.GroupDigits(data.current.price))) + end + + ESX.CloseContext() + parentShop.close() + OpenBuyWeaponsMenu() + else + ESX.ShowNotification(TranslateCap("armory_money")) + end + end, weaponName, 2, data.current.componentNum) + end + end) end function OpenGetStocksMenu() - ESX.TriggerServerCallback("esx_policejob:getStockItems", function(items) - local elements = { - { unselectable = true, icon = "fas fa-box", title = TranslateCap("police_stock") }, - } - - for i = 1, #items, 1 do - elements[#elements + 1] = { - icon = "fas fa-box", - title = "x" .. items[i].count .. " " .. items[i].label, - value = items[i].name, - } - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - local itemName = data.current.value - - local elements2 = { - { unselectable = true, icon = "fas fa-box", title = element.title }, - { - title = TranslateCap("quantity"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 150, - inputPlaceholder = TranslateCap("quantity_placeholder"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2, element2) - local data2 = { value = menu2.eles[2].inputValue } - local count = tonumber(data2.value) - - if not count then - ESX.ShowNotification(TranslateCap("quantity_invalid")) - else - ESX.CloseContext() - TriggerServerEvent("esx_policejob:getStockItem", itemName, count) - - Wait(300) - OpenGetStocksMenu() - end - end) - end) - end) + ESX.TriggerServerCallback("esx_policejob:getStockItems", function(items) + local elements = { + { unselectable = true, icon = "fas fa-box", title = TranslateCap("police_stock") }, + } + + for i = 1, #items, 1 do + elements[#elements + 1] = { + icon = "fas fa-box", + title = "x" .. items[i].count .. " " .. items[i].label, + value = items[i].name, + } + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + local itemName = data.current.value + + local elements2 = { + { unselectable = true, icon = "fas fa-box", title = element.title }, + { + title = TranslateCap("quantity"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 150, + inputPlaceholder = TranslateCap("quantity_placeholder"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2, element2) + local data2 = { value = menu2.eles[2].inputValue } + local count = tonumber(data2.value) + + if not count then + ESX.ShowNotification(TranslateCap("quantity_invalid")) + else + ESX.CloseContext() + TriggerServerEvent("esx_policejob:getStockItem", itemName, count) + + Wait(300) + OpenGetStocksMenu() + end + end) + end) + end) end function OpenPutStocksMenu() - ESX.TriggerServerCallback("esx_policejob:getPlayerInventory", function(inventory) - local elements = { - { unselectable = true, icon = "fas fa-box", title = TranslateCap("inventory") }, - } - - for i = 1, #inventory.items, 1 do - local item = inventory.items[i] - - if item.count > 0 then - elements[#elements + 1] = { - icon = "fas fa-box", - title = item.label .. " x" .. item.count, - type = "item_standard", - value = item.name, - } - end - end - - ESX.OpenContext("right", elements, function(menu, element) - local data = { current = element } - local itemName = data.current.value - - local elements2 = { - { unselectable = true, icon = "fas fa-box", title = element.title }, - { - title = TranslateCap("quantity"), - input = true, - inputType = "number", - inputMin = 1, - inputMax = 150, - inputPlaceholder = TranslateCap("quantity_placeholder"), - }, - { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, - } - - ESX.OpenContext("right", elements2, function(menu2, element2) - local data2 = { value = menu2.eles[2].inputValue } - local count = tonumber(data2.value) - - if not count then - ESX.ShowNotification(TranslateCap("quantity_invalid")) - else - ESX.CloseContext() - TriggerServerEvent("esx_policejob:putStockItems", itemName, count) - - Wait(300) - OpenPutStocksMenu() - end - end) - end) - end) + ESX.TriggerServerCallback("esx_policejob:getPlayerInventory", function(inventory) + local elements = { + { unselectable = true, icon = "fas fa-box", title = TranslateCap("inventory") }, + } + + for i = 1, #inventory.items, 1 do + local item = inventory.items[i] + + if item.count > 0 then + elements[#elements + 1] = { + icon = "fas fa-box", + title = item.label .. " x" .. item.count, + type = "item_standard", + value = item.name, + } + end + end + + ESX.OpenContext("right", elements, function(menu, element) + local data = { current = element } + local itemName = data.current.value + + local elements2 = { + { unselectable = true, icon = "fas fa-box", title = element.title }, + { + title = TranslateCap("quantity"), + input = true, + inputType = "number", + inputMin = 1, + inputMax = 150, + inputPlaceholder = TranslateCap("quantity_placeholder"), + }, + { icon = "fas fa-check-double", title = TranslateCap("confirm"), value = "confirm" }, + } + + ESX.OpenContext("right", elements2, function(menu2, element2) + local data2 = { value = menu2.eles[2].inputValue } + local count = tonumber(data2.value) + + if not count then + ESX.ShowNotification(TranslateCap("quantity_invalid")) + else + ESX.CloseContext() + TriggerServerEvent("esx_policejob:putStockItems", itemName, count) + + Wait(300) + OpenPutStocksMenu() + end + end) + end) + end) end function OnPlayerData(k, v) - if k ~= "job" then - return - end - if v.name == "police" then - Wait(1000) - TriggerServerEvent("esx_policejob:forceBlip") - end + if k ~= "job" then + return + end + if v.name == "police" then + Wait(1000) + TriggerServerEvent("esx_policejob:forceBlip") + end end RegisterNetEvent("esx_phone:loaded") AddEventHandler("esx_phone:loaded", function(phoneNumber, contacts) - local specialContact = { - name = TranslateCap("phone_police"), - number = "police", - base64Icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDFGQTJDRkI0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDFGQTJDRkM0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MUZBMkNGOTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MUZBMkNGQTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoW66EYAAAjGSURBVHjapJcLcFTV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", - } + local specialContact = { + name = TranslateCap("phone_police"), + number = "police", + base64Icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDFGQTJDRkI0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDFGQTJDRkM0QUJCMTFFN0JBNkQ5OENBMUI4QUEzM0YiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MUZBMkNGOTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MUZBMkNGQTRBQkIxMUU3QkE2RDk4Q0ExQjhBQTMzRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoW66EYAAAjGSURBVHjapJcLcFTV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", + } - TriggerEvent("esx_phone:addSpecialContact", specialContact.name, specialContact.number, specialContact.base64Icon) + TriggerEvent("esx_phone:addSpecialContact", specialContact.name, specialContact.number, specialContact.base64Icon) end) -- don't show dispatches if the player isn't in service AddEventHandler("esx_phone:cancelMessage", function(dispatchNumber) - if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" and ESX.PlayerData.job.name == dispatchNumber then - -- if esx_service is enabled - if Config.EnableESXService and not playerInService then - CancelEvent() - end - end + if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" and ESX.PlayerData.job.name == dispatchNumber then + -- if esx_service is enabled + if Config.EnableESXService and not playerInService then + CancelEvent() + end + end end) AddEventHandler("esx_policejob:hasEnteredMarker", function(station, part, partNum) - if part == "Cloakroom" then - CurrentAction = "menu_cloakroom" - CurrentActionMsg = TranslateCap("open_cloackroom") - CurrentActionData = {} - elseif part == "Armory" then - CurrentAction = "menu_armory" - CurrentActionMsg = TranslateCap("open_armory") - CurrentActionData = { station = station } - elseif part == "Vehicles" then - CurrentAction = "menu_vehicle_spawner" - CurrentActionMsg = TranslateCap("garage_prompt") - CurrentActionData = { station = station, part = part, partNum = partNum } - elseif part == "Helicopters" then - CurrentAction = "Helicopters" - CurrentActionMsg = TranslateCap("helicopter_prompt") - CurrentActionData = { station = station, part = part, partNum = partNum } - elseif part == "BossActions" then - CurrentAction = "menu_boss_actions" - CurrentActionMsg = TranslateCap("open_bossmenu") - CurrentActionData = {} - end + if part == "Cloakroom" then + CurrentAction = "menu_cloakroom" + CurrentActionMsg = TranslateCap("open_cloackroom") + CurrentActionData = {} + elseif part == "Armory" then + CurrentAction = "menu_armory" + CurrentActionMsg = TranslateCap("open_armory") + CurrentActionData = { station = station } + elseif part == "Vehicles" then + CurrentAction = "menu_vehicle_spawner" + CurrentActionMsg = TranslateCap("garage_prompt") + CurrentActionData = { station = station, part = part, partNum = partNum } + elseif part == "Helicopters" then + CurrentAction = "Helicopters" + CurrentActionMsg = TranslateCap("helicopter_prompt") + CurrentActionData = { station = station, part = part, partNum = partNum } + elseif part == "BossActions" then + CurrentAction = "menu_boss_actions" + CurrentActionMsg = TranslateCap("open_bossmenu") + CurrentActionData = {} + end end) AddEventHandler("esx_policejob:hasExitedMarker", function(station, part, partNum) - if not isInShopMenu then - ESX.CloseContext() - end + if not isInShopMenu then + ESX.CloseContext() + end - CurrentAction = nil + CurrentAction = nil end) AddEventHandler("esx_policejob:hasEnteredEntityZone", function(entity) - local playerPed = PlayerPedId() + local playerPed = PlayerPedId() - if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" and IsPedOnFoot(playerPed) then - CurrentAction = "remove_entity" - CurrentActionMsg = TranslateCap("remove_prop") - CurrentActionData = { entity = entity } - end + if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" and IsPedOnFoot(playerPed) then + CurrentAction = "remove_entity" + CurrentActionMsg = TranslateCap("remove_prop") + CurrentActionData = { entity = entity } + end - if GetEntityModel(entity) == `p_ld_stinger_s` then - local _ = GetEntityCoords(playerPed) + if GetEntityModel(entity) == `p_ld_stinger_s` then + local _ = GetEntityCoords(playerPed) - if IsPedInAnyVehicle(playerPed, false) then - local vehicle = GetVehiclePedIsIn(playerPed) + if IsPedInAnyVehicle(playerPed, false) then + local vehicle = GetVehiclePedIsIn(playerPed) - for i = 0, 7, 1 do - SetVehicleTyreBurst(vehicle, i, true, 1000) - end - end - end + 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 + if CurrentAction == "remove_entity" then + CurrentAction = nil + end end) RegisterNetEvent("esx_policejob:handcuff") AddEventHandler("esx_policejob:handcuff", function() - isHandcuffed = not isHandcuffed - local playerPed = PlayerPedId() - - if isHandcuffed then - RequestAnimDict("mp_arresting") - while not HasAnimDictLoaded("mp_arresting") do - Wait(100) - end - - TaskPlayAnim(playerPed, "mp_arresting", "idle", 8.0, -8, -1, 49, 0, 0, 0, 0) - RemoveAnimDict("mp_arresting") - - SetEnableHandcuffs(playerPed, true) - DisablePlayerFiring(playerPed, true) - SetCurrentPedWeapon(playerPed, `WEAPON_UNARMED`, true) -- unarm player - SetPedCanPlayGestureAnims(playerPed, false) - FreezeEntityPosition(playerPed, true) - DisplayRadar(false) - - if Config.EnableHandcuffTimer then - if handcuffTimer.active then - ESX.ClearTimeout(handcuffTimer.task) - end - - StartHandcuffTimer() - end - else - if Config.EnableHandcuffTimer and handcuffTimer.active then - ESX.ClearTimeout(handcuffTimer.task) - end - - ClearPedSecondaryTask(playerPed) - SetEnableHandcuffs(playerPed, false) - DisablePlayerFiring(playerPed, false) - SetPedCanPlayGestureAnims(playerPed, true) - FreezeEntityPosition(playerPed, false) - DisplayRadar(true) - end + isHandcuffed = not isHandcuffed + local playerPed = PlayerPedId() + + if isHandcuffed then + RequestAnimDict("mp_arresting") + while not HasAnimDictLoaded("mp_arresting") do + Wait(100) + end + + TaskPlayAnim(playerPed, "mp_arresting", "idle", 8.0, -8, -1, 49, 0, 0, 0, 0) + RemoveAnimDict("mp_arresting") + + SetEnableHandcuffs(playerPed, true) + DisablePlayerFiring(playerPed, true) + SetCurrentPedWeapon(playerPed, `WEAPON_UNARMED`, true) -- unarm player + SetPedCanPlayGestureAnims(playerPed, false) + FreezeEntityPosition(playerPed, true) + DisplayRadar(false) + + if Config.EnableHandcuffTimer then + if handcuffTimer.active then + ESX.ClearTimeout(handcuffTimer.task) + end + + StartHandcuffTimer() + end + else + if Config.EnableHandcuffTimer and handcuffTimer.active then + ESX.ClearTimeout(handcuffTimer.task) + end + + ClearPedSecondaryTask(playerPed) + SetEnableHandcuffs(playerPed, false) + DisablePlayerFiring(playerPed, false) + SetPedCanPlayGestureAnims(playerPed, true) + FreezeEntityPosition(playerPed, false) + DisplayRadar(true) + end end) RegisterNetEvent("esx_policejob:unrestrain") AddEventHandler("esx_policejob:unrestrain", function() - if isHandcuffed then - local playerPed = PlayerPedId() - isHandcuffed = false - - ClearPedSecondaryTask(playerPed) - SetEnableHandcuffs(playerPed, false) - DisablePlayerFiring(playerPed, false) - SetPedCanPlayGestureAnims(playerPed, true) - FreezeEntityPosition(playerPed, false) - DisplayRadar(true) - - -- end timer - if Config.EnableHandcuffTimer and handcuffTimer.active then - ESX.ClearTimeout(handcuffTimer.task) - end - end + if isHandcuffed then + local playerPed = PlayerPedId() + isHandcuffed = false + + ClearPedSecondaryTask(playerPed) + SetEnableHandcuffs(playerPed, false) + DisablePlayerFiring(playerPed, false) + SetPedCanPlayGestureAnims(playerPed, true) + FreezeEntityPosition(playerPed, false) + DisplayRadar(true) + + -- end timer + if Config.EnableHandcuffTimer and handcuffTimer.active then + ESX.ClearTimeout(handcuffTimer.task) + end + end end) RegisterNetEvent("esx_policejob:drag") AddEventHandler("esx_policejob:drag", function(copId) - if isHandcuffed then - dragStatus.isDragged = not dragStatus.isDragged - dragStatus.CopId = copId - end + if isHandcuffed then + dragStatus.isDragged = not dragStatus.isDragged + dragStatus.CopId = copId + end end) CreateThread(function() - local wasDragged - - while true do - local Sleep = 1500 - - if isHandcuffed and dragStatus.isDragged then - Sleep = 50 - local targetPed = GetPlayerPed(GetPlayerFromServerId(dragStatus.CopId)) - - if DoesEntityExist(targetPed) and IsPedOnFoot(targetPed) and not IsPedDeadOrDying(targetPed, true) then - if not wasDragged then - AttachEntityToEntity( - ESX.PlayerData.ped, - targetPed, - 11816, - 0.54, - 0.54, - 0.0, - 0.0, - 0.0, - 0.0, - false, - false, - false, - false, - 2, - true - ) - wasDragged = true - else - Wait(1000) - end - else - wasDragged = false - dragStatus.isDragged = false - DetachEntity(ESX.PlayerData.ped, true, false) - end - elseif wasDragged then - wasDragged = false - DetachEntity(ESX.PlayerData.ped, true, false) - end - Wait(Sleep) - end + local wasDragged + + while true do + local Sleep = 1500 + + if isHandcuffed and dragStatus.isDragged then + Sleep = 50 + local targetPed = GetPlayerPed(GetPlayerFromServerId(dragStatus.CopId)) + + if DoesEntityExist(targetPed) and IsPedOnFoot(targetPed) and not IsPedDeadOrDying(targetPed, true) then + if not wasDragged then + AttachEntityToEntity(ESX.PlayerData.ped, targetPed, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) + wasDragged = true + else + Wait(1000) + end + else + wasDragged = false + dragStatus.isDragged = false + DetachEntity(ESX.PlayerData.ped, true, false) + end + elseif wasDragged then + wasDragged = false + DetachEntity(ESX.PlayerData.ped, true, false) + end + Wait(Sleep) + end end) RegisterNetEvent("esx_policejob:putInVehicle") AddEventHandler("esx_policejob:putInVehicle", function() - if isHandcuffed then - local playerPed = PlayerPedId() - local vehicle, distance = ESX.Game.GetClosestVehicle() - - if vehicle and distance < 5 then - local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle) - - for i = maxSeats - 1, 0, -1 do - if IsVehicleSeatFree(vehicle, i) then - freeSeat = i - break - end - end - - if freeSeat then - TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat) - dragStatus.isDragged = false - end - end - end + if isHandcuffed then + local playerPed = PlayerPedId() + local vehicle, distance = ESX.Game.GetClosestVehicle() + + if vehicle and distance < 5 then + local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle) + + for i = maxSeats - 1, 0, -1 do + if IsVehicleSeatFree(vehicle, i) then + freeSeat = i + break + end + end + + if freeSeat then + TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat) + dragStatus.isDragged = false + end + end + end end) RegisterNetEvent("esx_policejob:OutVehicle") AddEventHandler("esx_policejob:OutVehicle", function() - local GetVehiclePedIsIn = GetVehiclePedIsIn - local IsPedSittingInAnyVehicle = IsPedSittingInAnyVehicle - local TaskLeaveVehicle = TaskLeaveVehicle - if IsPedSittingInAnyVehicle(ESX.PlayerData.ped) then - local vehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false) - TaskLeaveVehicle(ESX.PlayerData.ped, vehicle, 64) - end + local GetVehiclePedIsIn = GetVehiclePedIsIn + local IsPedSittingInAnyVehicle = IsPedSittingInAnyVehicle + local TaskLeaveVehicle = TaskLeaveVehicle + if IsPedSittingInAnyVehicle(ESX.PlayerData.ped) then + local vehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false) + TaskLeaveVehicle(ESX.PlayerData.ped, vehicle, 64) + end end) -- Handcuff CreateThread(function() - local DisableControlAction = DisableControlAction - local IsEntityPlayingAnim = IsEntityPlayingAnim - while true do - local Sleep = 1000 - - if isHandcuffed then - Sleep = 0 - DisableControlAction(0, 1, true) -- Disable pan - DisableControlAction(0, 2, true) -- Disable tilt - DisableControlAction(0, 24, true) -- Attack - DisableControlAction(0, 257, true) -- Attack 2 - DisableControlAction(0, 25, true) -- Aim - DisableControlAction(0, 263, true) -- Melee Attack 1 - DisableControlAction(0, 32, true) -- W - DisableControlAction(0, 34, true) -- A - DisableControlAction(0, 31, true) -- S - DisableControlAction(0, 30, true) -- D - - DisableControlAction(0, 45, true) -- Reload - DisableControlAction(0, 22, true) -- Jump - DisableControlAction(0, 44, true) -- Cover - DisableControlAction(0, 37, true) -- Select Weapon - DisableControlAction(0, 23, true) -- Also 'enter'? - - DisableControlAction(0, 288, true) -- Disable phone - DisableControlAction(0, 289, true) -- Inventory - DisableControlAction(0, 170, true) -- Animations - DisableControlAction(0, 167, true) -- Job - - DisableControlAction(0, 0, true) -- Disable changing view - DisableControlAction(0, 26, true) -- Disable looking behind - DisableControlAction(0, 73, true) -- Disable clearing animation - DisableControlAction(2, 199, true) -- Disable pause screen - - DisableControlAction(0, 59, true) -- Disable steering in vehicle - DisableControlAction(0, 71, true) -- Disable driving forward in vehicle - DisableControlAction(0, 72, true) -- Disable reversing in vehicle - - DisableControlAction(2, 36, true) -- Disable going stealth - - DisableControlAction(0, 47, true) -- Disable weapon - DisableControlAction(0, 264, true) -- Disable melee - DisableControlAction(0, 257, true) -- Disable melee - DisableControlAction(0, 140, true) -- Disable melee - DisableControlAction(0, 141, true) -- Disable melee - DisableControlAction(0, 142, true) -- Disable melee - DisableControlAction(0, 143, true) -- Disable melee - DisableControlAction(0, 75, true) -- Disable exit vehicle - DisableControlAction(27, 75, true) -- Disable exit vehicle - - if IsEntityPlayingAnim(ESX.PlayerData.ped, "mp_arresting", "idle", 3) ~= 1 then - ESX.Streaming.RequestAnimDict("mp_arresting", function() - TaskPlayAnim(ESX.PlayerData.ped, "mp_arresting", "idle", 8.0, -8, -1, 49, 0.0, false, false, false) - RemoveAnimDict("mp_arresting") - end) - end - end - Wait(Sleep) - end + local DisableControlAction = DisableControlAction + local IsEntityPlayingAnim = IsEntityPlayingAnim + while true do + local Sleep = 1000 + + if isHandcuffed then + Sleep = 0 + DisableControlAction(0, 1, true) -- Disable pan + DisableControlAction(0, 2, true) -- Disable tilt + DisableControlAction(0, 24, true) -- Attack + DisableControlAction(0, 257, true) -- Attack 2 + DisableControlAction(0, 25, true) -- Aim + DisableControlAction(0, 263, true) -- Melee Attack 1 + DisableControlAction(0, 32, true) -- W + DisableControlAction(0, 34, true) -- A + DisableControlAction(0, 31, true) -- S + DisableControlAction(0, 30, true) -- D + + DisableControlAction(0, 45, true) -- Reload + DisableControlAction(0, 22, true) -- Jump + DisableControlAction(0, 44, true) -- Cover + DisableControlAction(0, 37, true) -- Select Weapon + DisableControlAction(0, 23, true) -- Also 'enter'? + + DisableControlAction(0, 288, true) -- Disable phone + DisableControlAction(0, 289, true) -- Inventory + DisableControlAction(0, 170, true) -- Animations + DisableControlAction(0, 167, true) -- Job + + DisableControlAction(0, 0, true) -- Disable changing view + DisableControlAction(0, 26, true) -- Disable looking behind + DisableControlAction(0, 73, true) -- Disable clearing animation + DisableControlAction(2, 199, true) -- Disable pause screen + + DisableControlAction(0, 59, true) -- Disable steering in vehicle + DisableControlAction(0, 71, true) -- Disable driving forward in vehicle + DisableControlAction(0, 72, true) -- Disable reversing in vehicle + + DisableControlAction(2, 36, true) -- Disable going stealth + + DisableControlAction(0, 47, true) -- Disable weapon + DisableControlAction(0, 264, true) -- Disable melee + DisableControlAction(0, 257, true) -- Disable melee + DisableControlAction(0, 140, true) -- Disable melee + DisableControlAction(0, 141, true) -- Disable melee + DisableControlAction(0, 142, true) -- Disable melee + DisableControlAction(0, 143, true) -- Disable melee + DisableControlAction(0, 75, true) -- Disable exit vehicle + DisableControlAction(27, 75, true) -- Disable exit vehicle + + if IsEntityPlayingAnim(ESX.PlayerData.ped, "mp_arresting", "idle", 3) ~= 1 then + ESX.Streaming.RequestAnimDict("mp_arresting", function() + TaskPlayAnim(ESX.PlayerData.ped, "mp_arresting", "idle", 8.0, -8, -1, 49, 0.0, false, false, false) + RemoveAnimDict("mp_arresting") + end) + end + end + Wait(Sleep) + end end) -- Create blips CreateThread(function() - for _, v in pairs(Config.PoliceStations) do - local blip = AddBlipForCoord(v.Blip.Coords) - - SetBlipSprite(blip, v.Blip.Sprite) - SetBlipDisplay(blip, v.Blip.Display) - SetBlipScale(blip, v.Blip.Scale) - SetBlipColour(blip, v.Blip.Colour) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("map_blip")) - EndTextCommandSetBlipName(blip) - end + for _, v in pairs(Config.PoliceStations) do + local blip = AddBlipForCoord(v.Blip.Coords) + + SetBlipSprite(blip, v.Blip.Sprite) + SetBlipDisplay(blip, v.Blip.Display) + SetBlipScale(blip, v.Blip.Scale) + SetBlipColour(blip, v.Blip.Colour) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("map_blip")) + EndTextCommandSetBlipName(blip) + end end) -- Draw markers and more CreateThread(function() - while true do - local Sleep = 1500 - if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" then - Sleep = 500 - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - local isInMarker, hasExited = false, false - local currentStation, currentPart, currentPartNum - - for k, v in pairs(Config.PoliceStations) do - for i = 1, #v.Cloakrooms, 1 do - local distance = #(playerCoords - v.Cloakrooms[i]) - - if distance < Config.DrawDistance then - DrawMarker( - Config.MarkerType.Cloakrooms, - v.Cloakrooms[i], - 0.0, - 0.0, - 0.0, - 0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - true, - false, - false, - false - ) - Sleep = 0 - - if distance < Config.MarkerSize.x then - isInMarker, currentStation, currentPart, currentPartNum = true, k, "Cloakroom", i - end - end - end - - for i = 1, #v.Armories, 1 do - local distance = #(playerCoords - v.Armories[i]) - - if distance < Config.DrawDistance then - DrawMarker( - Config.MarkerType.Armories, - v.Armories[i], - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.5, - 0.5, - 0.5, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - true, - false, - false, - false - ) - Sleep = 0 - - if distance < Config.MarkerSize.x then - isInMarker, currentStation, currentPart, currentPartNum = true, k, "Armory", i - end - end - end - - for i = 1, #v.Vehicles, 1 do - local distance = #(playerCoords - v.Vehicles[i].Spawner) - - if distance < Config.DrawDistance then - DrawMarker( - Config.MarkerType.Vehicles, - v.Vehicles[i].Spawner, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - true, - false, - false, - false - ) - Sleep = 0 - - if distance < Config.MarkerSize.x then - isInMarker, currentStation, currentPart, currentPartNum = true, k, "Vehicles", i - end - end - end - - for i = 1, #v.Helicopters, 1 do - local distance = #(playerCoords - v.Helicopters[i].Spawner) - - if distance < Config.DrawDistance then - DrawMarker( - Config.MarkerType.Helicopters, - v.Helicopters[i].Spawner, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - true, - false, - false, - false - ) - Sleep = 0 - - if distance < Config.MarkerSize.x then - isInMarker, currentStation, currentPart, currentPartNum = true, k, "Helicopters", i - end - end - end - - if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == "boss" then - for i = 1, #v.BossActions, 1 do - local distance = #(playerCoords - v.BossActions[i]) - - if distance < Config.DrawDistance then - DrawMarker( - Config.MarkerType.BossActions, - v.BossActions[i], - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - true, - false, - false, - false - ) - Sleep = 0 - - if distance < Config.MarkerSize.x then - isInMarker, currentStation, currentPart, currentPartNum = true, k, "BossActions", i - end - end - end - end - end - - if - isInMarker and not HasAlreadyEnteredMarker - or ( - isInMarker - and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum) - ) - then - if - (LastStation and LastPart and LastPartNum) - and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum) - then - TriggerEvent("esx_policejob:hasExitedMarker", LastStation, LastPart, LastPartNum) - hasExited = true - end - - HasAlreadyEnteredMarker = true - LastStation = currentStation - LastPart = currentPart - LastPartNum = currentPartNum - - TriggerEvent("esx_policejob:hasEnteredMarker", currentStation, currentPart, currentPartNum) - end - - if not hasExited and not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - TriggerEvent("esx_policejob:hasExitedMarker", LastStation, LastPart, LastPartNum) - end - end - Wait(Sleep) - end + while true do + local Sleep = 1500 + if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" then + Sleep = 500 + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + local isInMarker, hasExited = false, false + local currentStation, currentPart, currentPartNum + + for k, v in pairs(Config.PoliceStations) do + for i = 1, #v.Cloakrooms, 1 do + local distance = #(playerCoords - v.Cloakrooms[i]) + + if distance < Config.DrawDistance then + DrawMarker(Config.MarkerType.Cloakrooms, v.Cloakrooms[i], 0.0, 0.0, 0.0, 0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) + Sleep = 0 + + if distance < Config.MarkerSize.x then + isInMarker, currentStation, currentPart, currentPartNum = true, k, "Cloakroom", i + end + end + end + + for i = 1, #v.Armories, 1 do + local distance = #(playerCoords - v.Armories[i]) + + if distance < Config.DrawDistance then + DrawMarker(Config.MarkerType.Armories, v.Armories[i], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) + Sleep = 0 + + if distance < Config.MarkerSize.x then + isInMarker, currentStation, currentPart, currentPartNum = true, k, "Armory", i + end + end + end + + for i = 1, #v.Vehicles, 1 do + local distance = #(playerCoords - v.Vehicles[i].Spawner) + + if distance < Config.DrawDistance then + DrawMarker(Config.MarkerType.Vehicles, v.Vehicles[i].Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) + Sleep = 0 + + if distance < Config.MarkerSize.x then + isInMarker, currentStation, currentPart, currentPartNum = true, k, "Vehicles", i + end + end + end + + for i = 1, #v.Helicopters, 1 do + local distance = #(playerCoords - v.Helicopters[i].Spawner) + + if distance < Config.DrawDistance then + DrawMarker(Config.MarkerType.Helicopters, v.Helicopters[i].Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) + Sleep = 0 + + if distance < Config.MarkerSize.x then + isInMarker, currentStation, currentPart, currentPartNum = true, k, "Helicopters", i + end + end + end + + if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == "boss" then + for i = 1, #v.BossActions, 1 do + local distance = #(playerCoords - v.BossActions[i]) + + if distance < Config.DrawDistance then + DrawMarker(Config.MarkerType.BossActions, v.BossActions[i], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, true, false, false, false) + Sleep = 0 + + if distance < Config.MarkerSize.x then + isInMarker, currentStation, currentPart, currentPartNum = true, k, "BossActions", i + end + end + end + end + end + + if isInMarker and not HasAlreadyEnteredMarker or (isInMarker and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum)) then + if (LastStation and LastPart and LastPartNum) and (LastStation ~= currentStation or LastPart ~= currentPart or LastPartNum ~= currentPartNum) then + TriggerEvent("esx_policejob:hasExitedMarker", LastStation, LastPart, LastPartNum) + hasExited = true + end + + HasAlreadyEnteredMarker = true + LastStation = currentStation + LastPart = currentPart + LastPartNum = currentPartNum + + TriggerEvent("esx_policejob:hasEnteredMarker", currentStation, currentPart, currentPartNum) + end + + if not hasExited and not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + TriggerEvent("esx_policejob:hasExitedMarker", LastStation, LastPart, LastPartNum) + end + end + Wait(Sleep) + end end) -- Enter / Exit entity zone events CreateThread(function() - local trackedEntities = { - `prop_roadcone02a`, - `prop_barrier_work05`, - `p_ld_stinger_s`, - `prop_boxpile_07d`, - `hei_prop_cash_crate_half_full`, - } - - while true do - local Sleep = 1500 - - local GetEntityCoords = GetEntityCoords - local GetClosestObjectOfType = GetClosestObjectOfType - local DoesEntityExist = DoesEntityExist - local playerCoords = GetEntityCoords(ESX.PlayerData.ped) - - local closestDistance = -1 - local closestEntity = nil - - for i = 1, #trackedEntities, 1 do - local object = GetClosestObjectOfType(playerCoords, 3.0, trackedEntities[i], false, false, false) - - if DoesEntityExist(object) then - Sleep = 500 - local objCoords = GetEntityCoords(object) - local distance = #(playerCoords - objCoords) - - if closestDistance == -1 or closestDistance > distance then - closestDistance = distance - closestEntity = object - end - end - end - - if closestDistance ~= -1 and closestDistance <= 3.0 then - if LastEntity ~= closestEntity then - TriggerEvent("esx_policejob:hasEnteredEntityZone", closestEntity) - LastEntity = closestEntity - end - else - if LastEntity then - TriggerEvent("esx_policejob:hasExitedEntityZone", LastEntity) - LastEntity = nil - end - end - Wait(Sleep) - end + local trackedEntities = { + `prop_roadcone02a`, + `prop_barrier_work05`, + `p_ld_stinger_s`, + `prop_boxpile_07d`, + `hei_prop_cash_crate_half_full`, + } + + while true do + local Sleep = 1500 + + local GetEntityCoords = GetEntityCoords + local GetClosestObjectOfType = GetClosestObjectOfType + local DoesEntityExist = DoesEntityExist + local playerCoords = GetEntityCoords(ESX.PlayerData.ped) + + local closestDistance = -1 + local closestEntity = nil + + for i = 1, #trackedEntities, 1 do + local object = GetClosestObjectOfType(playerCoords, 3.0, trackedEntities[i], false, false, false) + + if DoesEntityExist(object) then + Sleep = 500 + local objCoords = GetEntityCoords(object) + local distance = #(playerCoords - objCoords) + + if closestDistance == -1 or closestDistance > distance then + closestDistance = distance + closestEntity = object + end + end + end + + if closestDistance ~= -1 and closestDistance <= 3.0 then + if LastEntity ~= closestEntity then + TriggerEvent("esx_policejob:hasEnteredEntityZone", closestEntity) + LastEntity = closestEntity + end + else + if LastEntity then + TriggerEvent("esx_policejob:hasExitedEntityZone", LastEntity) + LastEntity = nil + end + end + Wait(Sleep) + end end) ESX.RegisterInput("police:interact", "(ESX PoliceJob) " .. TranslateCap("interaction"), "keyboard", "E", function() - if not CurrentAction then - return - end - - if CurrentAction == "menu_cloakroom" then - OpenCloakroomMenu() - elseif CurrentAction == "menu_armory" then - if not Config.EnableESXService then - OpenArmoryMenu(CurrentActionData.station) - elseif playerInService then - OpenArmoryMenu(CurrentActionData.station) - else - ESX.ShowNotification(TranslateCap("service_not")) - end - elseif CurrentAction == "menu_vehicle_spawner" then - if not Config.EnableESXService then - OpenVehicleSpawnerMenu("car", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) - elseif playerInService then - OpenVehicleSpawnerMenu("car", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) - else - ESX.ShowNotification(TranslateCap("service_not")) - end - elseif CurrentAction == "Helicopters" then - if not Config.EnableESXService then - OpenVehicleSpawnerMenu( - "helicopter", - CurrentActionData.station, - CurrentActionData.part, - CurrentActionData.partNum - ) - elseif playerInService then - OpenVehicleSpawnerMenu( - "helicopter", - CurrentActionData.station, - CurrentActionData.part, - CurrentActionData.partNum - ) - else - ESX.ShowNotification(TranslateCap("service_not")) - end - elseif CurrentAction == "delete_vehicle" then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - elseif CurrentAction == "menu_boss_actions" then - ESX.CloseContext() - TriggerEvent("esx_society:openBossMenu", "police", function(data, menu) - ESX.CloseContext() - - CurrentAction = "menu_boss_actions" - CurrentActionMsg = TranslateCap("open_bossmenu") - CurrentActionData = {} - end, { wash = false }) -- disable washing money - elseif CurrentAction == "remove_entity" then - DeleteEntity(CurrentActionData.entity) - end - - if not ESX.PlayerData.job or (ESX.PlayerData.job and not ESX.PlayerData.job.name == "police") then - return - end - - CurrentAction = nil + if not CurrentAction then + return + end + + if CurrentAction == "menu_cloakroom" then + OpenCloakroomMenu() + elseif CurrentAction == "menu_armory" then + if not Config.EnableESXService then + OpenArmoryMenu(CurrentActionData.station) + elseif playerInService then + OpenArmoryMenu(CurrentActionData.station) + else + ESX.ShowNotification(TranslateCap("service_not")) + end + elseif CurrentAction == "menu_vehicle_spawner" then + if not Config.EnableESXService then + OpenVehicleSpawnerMenu("car", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) + elseif playerInService then + OpenVehicleSpawnerMenu("car", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) + else + ESX.ShowNotification(TranslateCap("service_not")) + end + elseif CurrentAction == "Helicopters" then + if not Config.EnableESXService then + OpenVehicleSpawnerMenu("helicopter", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) + elseif playerInService then + OpenVehicleSpawnerMenu("helicopter", CurrentActionData.station, CurrentActionData.part, CurrentActionData.partNum) + else + ESX.ShowNotification(TranslateCap("service_not")) + end + elseif CurrentAction == "delete_vehicle" then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + elseif CurrentAction == "menu_boss_actions" then + ESX.CloseContext() + TriggerEvent("esx_society:openBossMenu", "police", function(data, menu) + ESX.CloseContext() + + CurrentAction = "menu_boss_actions" + CurrentActionMsg = TranslateCap("open_bossmenu") + CurrentActionData = {} + end, { wash = false }) -- disable washing money + elseif CurrentAction == "remove_entity" then + DeleteEntity(CurrentActionData.entity) + end + + if not ESX.PlayerData.job or (ESX.PlayerData.job and not ESX.PlayerData.job.name == "police") then + return + end + + CurrentAction = nil end) -ESX.RegisterInput( - "police:quickactions", - "(ESX PoliceJob) " .. TranslateCap("quick_actions"), - "keyboard", - "F6", - function() - if not ESX.PlayerData.job or (ESX.PlayerData.job.name ~= "police") or isDead then - return - end - - if not Config.EnableESXService then - OpenPoliceActionsMenu() - elseif playerInService then - OpenPoliceActionsMenu() - else - ESX.ShowNotification(TranslateCap("service_not")) - end - end -) +ESX.RegisterInput("police:quickactions", "(ESX PoliceJob) " .. TranslateCap("quick_actions"), "keyboard", "F6", function() + if not ESX.PlayerData.job or (ESX.PlayerData.job.name ~= "police") or isDead then + return + end + + if not Config.EnableESXService then + OpenPoliceActionsMenu() + elseif playerInService then + OpenPoliceActionsMenu() + else + ESX.ShowNotification(TranslateCap("service_not")) + end +end) CreateThread(function() - while true do - local Sleep = 1000 - - if CurrentAction then - Sleep = 0 - ESX.ShowHelpNotification(CurrentActionMsg) - end - Wait(Sleep) - end + while true do + local Sleep = 1000 + + if CurrentAction then + Sleep = 0 + ESX.ShowHelpNotification(CurrentActionMsg) + end + Wait(Sleep) + end end) -- Create blip for colleagues function createBlip(id) - local ped = GetPlayerPed(id) - local blip = GetBlipFromEntity(ped) - - if not DoesBlipExist(blip) then -- Add blip and create head display on player - blip = AddBlipForEntity(ped) - SetBlipSprite(blip, 1) - ShowHeadingIndicatorOnBlip(blip, true) -- Player Blip indicator - SetBlipRotation(blip, math.ceil(GetEntityHeading(ped))) -- update rotation - SetBlipNameToPlayerName(blip, id) -- update blip name - SetBlipScale(blip, 0.85) -- set scale - SetBlipAsShortRange(blip, true) - - table.insert(blipsCops, blip) -- add blip to array so we can remove it later - end + local ped = GetPlayerPed(id) + local blip = GetBlipFromEntity(ped) + + if not DoesBlipExist(blip) then -- Add blip and create head display on player + blip = AddBlipForEntity(ped) + SetBlipSprite(blip, 1) + ShowHeadingIndicatorOnBlip(blip, true) -- Player Blip indicator + SetBlipRotation(blip, math.ceil(GetEntityHeading(ped))) -- update rotation + SetBlipNameToPlayerName(blip, id) -- update blip name + SetBlipScale(blip, 0.85) -- set scale + SetBlipAsShortRange(blip, true) + + table.insert(blipsCops, blip) -- add blip to array so we can remove it later + end end RegisterNetEvent("esx_policejob:updateBlip") AddEventHandler("esx_policejob:updateBlip", function() - -- Refresh all blips - for _, existingBlip in pairs(blipsCops) do - RemoveBlip(existingBlip) - end - - -- Clean the blip table - blipsCops = {} - - -- Enable blip? - if Config.EnableESXService and not playerInService then - return - end - - if not Config.EnableJobBlip then - return - end - - -- Is the player a cop? In that case show all the blips for other cops - if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" then - ESX.TriggerServerCallback("esx_society:getOnlinePlayers", function(players) - for i = 1, #players, 1 do - if players[i].job.name == "police" then - local id = GetPlayerFromServerId(players[i].source) - if NetworkIsPlayerActive(id) and GetPlayerPed(id) ~= PlayerPedId() then - createBlip(id) - end - end - end - end) - end + -- Refresh all blips + for _, existingBlip in pairs(blipsCops) do + RemoveBlip(existingBlip) + end + + -- Clean the blip table + blipsCops = {} + + -- Enable blip? + if Config.EnableESXService and not playerInService then + return + end + + if not Config.EnableJobBlip then + return + end + + -- Is the player a cop? In that case show all the blips for other cops + if ESX.PlayerData.job and ESX.PlayerData.job.name == "police" then + ESX.TriggerServerCallback("esx_society:getOnlinePlayers", function(players) + for i = 1, #players, 1 do + if players[i].job.name == "police" then + local id = GetPlayerFromServerId(players[i].source) + if NetworkIsPlayerActive(id) and GetPlayerPed(id) ~= PlayerPedId() then + createBlip(id) + end + end + end + end) + end end) AddEventHandler("esx:onPlayerSpawn", function(spawn) - isDead = false - TriggerEvent("esx_policejob:unrestrain") + isDead = false + TriggerEvent("esx_policejob:unrestrain") - if not hasAlreadyJoined then - TriggerServerEvent("esx_policejob:spawned") - end - hasAlreadyJoined = true + if not hasAlreadyJoined then + TriggerServerEvent("esx_policejob:spawned") + end + hasAlreadyJoined = true end) AddEventHandler("esx:onPlayerDeath", function(data) - isDead = true + isDead = true end) AddEventHandler("onResourceStop", function(resource) - if resource == GetCurrentResourceName() then - TriggerEvent("esx_policejob:unrestrain") - TriggerEvent("esx_phone:removeSpecialContact", "police") - - if Config.EnableESXService then - TriggerServerEvent("esx_service:disableService", "police") - end - - if Config.EnableHandcuffTimer and handcuffTimer.active then - ESX.ClearTimeout(handcuffTimer.task) - end - end + if resource == GetCurrentResourceName() then + TriggerEvent("esx_policejob:unrestrain") + TriggerEvent("esx_phone:removeSpecialContact", "police") + + if Config.EnableESXService then + TriggerServerEvent("esx_service:disableService", "police") + end + + if Config.EnableHandcuffTimer and handcuffTimer.active then + ESX.ClearTimeout(handcuffTimer.task) + end + end end) -- handcuff timer, unrestrain the player after an certain amount of time function StartHandcuffTimer() - if Config.EnableHandcuffTimer and handcuffTimer.active then - ESX.ClearTimeout(handcuffTimer.task) - end + if Config.EnableHandcuffTimer and handcuffTimer.active then + ESX.ClearTimeout(handcuffTimer.task) + end - handcuffTimer.active = true + handcuffTimer.active = true - handcuffTimer.task = ESX.SetTimeout(Config.HandcuffTimer, function() - ESX.ShowNotification(TranslateCap("unrestrained_timer")) - TriggerEvent("esx_policejob:unrestrain") - handcuffTimer.active = false - end) + handcuffTimer.task = ESX.SetTimeout(Config.HandcuffTimer, function() + ESX.ShowNotification(TranslateCap("unrestrained_timer")) + TriggerEvent("esx_policejob:unrestrain") + handcuffTimer.active = false + end) end -- TODO -- - return to garage if owned -- - message owner that his vehicle has been impounded function ImpoundVehicle(vehicle) - ESX.Game.DeleteVehicle(vehicle) - ESX.ShowNotification(TranslateCap("impound_successful")) - currentTask.busy = false + ESX.Game.DeleteVehicle(vehicle) + ESX.ShowNotification(TranslateCap("impound_successful")) + currentTask.busy = false end if ESX.PlayerLoaded and ESX.PlayerData.job == "police" then - SetTimeout(1000, function() - TriggerServerEvent("esx_policejob:forceBlip") - end) + SetTimeout(1000, function() + TriggerServerEvent("esx_policejob:forceBlip") + end) end diff --git a/server-data/resources/[esx_addons]/esx_policejob/fxmanifest.lua b/server-data/resources/[esx_addons]/esx_policejob/fxmanifest.lua index bc56d6a6b..f399db01c 100644 --- a/server-data/resources/[esx_addons]/esx_policejob/fxmanifest.lua +++ b/server-data/resources/[esx_addons]/esx_policejob/fxmanifest.lua @@ -25,6 +25,6 @@ client_scripts { dependencies { 'es_extended', - 'esx_billing', + 'bpt_billing', 'esx_vehicleshop' } diff --git a/server-data/resources/[esx_addons]/esx_vehicleshop/README.md b/server-data/resources/[esx_addons]/esx_vehicleshop/README.md index 121be8cf8..4597dc5be 100644 --- a/server-data/resources/[esx_addons]/esx_vehicleshop/README.md +++ b/server-data/resources/[esx_addons]/esx_vehicleshop/README.md @@ -9,7 +9,6 @@ ESX Vehicle Shop adds an vehicle shop to the game, where employeed players can s * Player management (the car dealer job): billing, boss actions and more! * [esx_society] - * [esx_billing] * [cron] ### Installation diff --git a/server-data/resources/[esx_addons]/esx_vehicleshop/client/main.lua b/server-data/resources/[esx_addons]/esx_vehicleshop/client/main.lua index 10f424736..62059119d 100644 --- a/server-data/resources/[esx_addons]/esx_vehicleshop/client/main.lua +++ b/server-data/resources/[esx_addons]/esx_vehicleshop/client/main.lua @@ -1,19 +1,9 @@ local Config = Config local HasAlreadyEnteredMarker, IsInShopMenu = false, false local CurrentAction, CurrentActionMsg, LastZone, currentDisplayVehicle, CurrentVehicleData -local CurrentActionData, Vehicles, Categories, VehiclesByModel, vehiclesByCategory, soldVehicles, cardealerVehicles, rentedVehicles = - {}, {}, {}, {}, {}, {}, {}, {} +local CurrentActionData, Vehicles, Categories, VehiclesByModel, vehiclesByCategory, soldVehicles, cardealerVehicles, rentedVehicles = {}, {}, {}, {}, {}, {}, {}, {} local DoesEntityExist, NetworkRequestControlOfEntity, NetworkHasControlOfEntity, DisableControlAction, HasModelLoaded, RequestModel, DisableAllControlActions, FreezeEntityPosition, SetEntityCoords, SetEntityVisible = - DoesEntityExist, - NetworkRequestControlOfEntity, - NetworkHasControlOfEntity, - DisableControlAction, - HasModelLoaded, - RequestModel, - DisableAllControlActions, - FreezeEntityPosition, - SetEntityCoords, - SetEntityVisible + DoesEntityExist, NetworkRequestControlOfEntity, NetworkHasControlOfEntity, DisableControlAction, HasModelLoaded, RequestModel, DisableAllControlActions, FreezeEntityPosition, SetEntityCoords, SetEntityVisible Vehicles = GlobalState.vehicleShop.vehicles Categories = GlobalState.vehicleShop.categories @@ -23,954 +13,858 @@ cardealerVehicles = GlobalState.vehicleShop.cardealerVehicles rentedVehicles = GlobalState.vehicleShop.rentedVehicles AddStateBagChangeHandler("vehicleShop", "global", function(bagName, key, value) - Vehicles = value.vehicles - Categories = value.categories - VehiclesByModel = value.vehiclesByModel - soldVehicles = value.soldVehicles - cardealerVehicles = value.cardealerVehicles - rentedVehicles = value.rentedVehicles + Vehicles = value.vehicles + Categories = value.categories + VehiclesByModel = value.vehiclesByModel + soldVehicles = value.soldVehicles + cardealerVehicles = value.cardealerVehicles + rentedVehicles = value.rentedVehicles end) CreateThread(function() - while true do - Wait(60000) - collectgarbage("collect") - end + while true do + Wait(60000) + collectgarbage("collect") + end end) local function getVehicleFromModel(model) - return VehiclesByModel[model] + return VehiclesByModel[model] end local function Init() - TriggerEvent("esx_vehicleshop:updateTables") - - Wait(500) - - table.sort(Vehicles, function(a, b) - return a.name < b.name - end) - - for i = 1, #Vehicles, 1 do - local vehicle = Vehicles[i] - if IsModelInCdimage(joaat(vehicle.model)) then - local category = vehicle.category - - if not vehiclesByCategory[category] then - vehiclesByCategory[category] = {} - end - - table.insert(vehiclesByCategory[category], vehicle) - else - print(("[^3WARNING^7] Ignoring vehicle ^5%s^7 due to invalid Model"):format(vehicle.model)) - end - end - - if Config.EnablePlayerManagement then - RegisterNetEvent("esx_phone:loaded") - AddEventHandler("esx_phone:loaded", function(phoneNumber, contacts) - local specialContact = { - name = TranslateCap("dealership"), - number = "cardealer", - base64Icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAADMzMzszM0M0M0w0M1Q1M101M2U2M242M3Y3M383Moc4MpA4Mpg5MqE5Mqk6MrI6Mro7Mrw8Mr89M71DML5EO8I+NMU/NcBMLshANctBNs5CN8RULMddKsheKs9YLtBCONZEOdlFOtxGO99HPNhMNsplKM1nKM1uJtRhLddiLt5kMNJwJ9B2JNR/IeNIPeVJPehKPuRQOuhSO+lZOOlhNuloM+p3Lep/KupwMMFORsVYUcplXc1waNJ7delUSepgVexrYe12bdeHH9iIH9qQHd2YG+udH+OEJeuGJ+uOJeuVIuChGeSpF+aqGOykHOysGeeyFeuzFuyzFuq6E+27FO+Cee3CEdaGgdqTjvCNhfKYkvOkngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJezdycAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjb9TgnoAAAQGElEQVR4Xt2d+WMUtxXHbS6bEGMPMcQQ04aEUnqYo9xJWvC6kAKmQLM2rdn//9+g0uir2Tl0PElPszP7+cnH7Fj6rPTeG2lmvfKld2azk8lk/36L/cnkZDbDIT3Sp4DZ8QS9dTI57tNDTwJOOu+4j/0TvDQz+QXMSG+7mUn+sZBZQELnNROcKhMZBXx+gS4k8+IzTpmBXAJOnqPxTDzPFRKyCODuvSKPgwwC2EZ+lxf4E4xwCzhBU7PBPQx4BWR88+fwDgNGAbMsM9/Ec8bygE3A5966L3nOlhiZBGSf+l2YggGLgBna1DMsE4FBQH9zvw1HLEgX0Evkt5GeEVIFMFztpJF6rZQm4DNasVDSEkKSgIVN/ibP0ZwoEgQsfPTPSZgH8QIG8vYr4gdBrIABvf2K2EEQKWBQb78ichBECRhE8O8SlQ5iBAQvcffFPhoYQoSAAQ5/TcQ0CBYw0OGvCZ4GoQIGF/3bhGaDQAELvfKhERgIwgQMePrPCQsEQQLwFwYPmksiQMCC1n1iCFgooQtYwLJfPPQFQ7KAUfU/wABVwMj6TzdAFDDY6tcOMR3SBIyw/1QDJAGj7D/RAEXA6Oa/hhIHCAJG23+SAb+AEfefYsArYET1nwlvTegVgBONFnTDik8ATjNi0BEbHgGjuP5147k6dgsYaQHQxF0OOAUMfv2LhnOVzCVg4OufdFwrpS4BePkSgA6ZcAhYggCocQRCu4ClCIAaeyC0CliaAKCwhgGrALxwaUC3OtgELFEAUNjCgEXAklQAdSzVgEUAXrRUoGstzAKWbgJIzJPAKGAJJ4DEOAmMAvCCpQPda2ASsJQTQGKa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", - } - - TriggerEvent( - "esx_phone:addSpecialContact", - specialContact.name, - specialContact.number, - specialContact.base64Icon - ) - end) - end - - if Config.Blip.show then - CreateThread(function() - local blip = AddBlipForCoord(Config.Zones.ShopEntering.Pos) - - SetBlipSprite(blip, Config.Blip.Sprite) - SetBlipDisplay(blip, Config.Blip.Display) - SetBlipScale(blip, Config.Blip.Scale) - SetBlipAsShortRange(blip, true) - - BeginTextCommandSetBlipName("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("car_dealer")) - EndTextCommandSetBlipName(blip) - end) - end - - return true + TriggerEvent("esx_vehicleshop:updateTables") + + Wait(500) + + table.sort(Vehicles, function(a, b) + return a.name < b.name + end) + + for i = 1, #Vehicles, 1 do + local vehicle = Vehicles[i] + if IsModelInCdimage(joaat(vehicle.model)) then + local category = vehicle.category + + if not vehiclesByCategory[category] then + vehiclesByCategory[category] = {} + end + + table.insert(vehiclesByCategory[category], vehicle) + else + print(("[^3WARNING^7] Ignoring vehicle ^5%s^7 due to invalid Model"):format(vehicle.model)) + end + end + + if Config.EnablePlayerManagement then + RegisterNetEvent("esx_phone:loaded") + AddEventHandler("esx_phone:loaded", function(phoneNumber, contacts) + local specialContact = { + name = TranslateCap("dealership"), + number = "cardealer", + base64Icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAADMzMzszM0M0M0w0M1Q1M101M2U2M242M3Y3M383Moc4MpA4Mpg5MqE5Mqk6MrI6Mro7Mrw8Mr89M71DML5EO8I+NMU/NcBMLshANctBNs5CN8RULMddKsheKs9YLtBCONZEOdlFOtxGO99HPNhMNsplKM1nKM1uJtRhLddiLt5kMNJwJ9B2JNR/IeNIPeVJPehKPuRQOuhSO+lZOOlhNuloM+p3Lep/KupwMMFORsVYUcplXc1waNJ7delUSepgVexrYe12bdeHH9iIH9qQHd2YG+udH+OEJeuGJ+uOJeuVIuChGeSpF+aqGOykHOysGeeyFeuzFuyzFuq6E+27FO+Cee3CEdaGgdqTjvCNhfKYkvOkngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJezdycAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjb9TgnoAAAQGElEQVR4Xt2d+WMUtxXHbS6bEGMPMcQQ04aEUnqYo9xJWvC6kAKmQLM2rdn//9+g0uir2Tl0PElPszP7+cnH7Fj6rPTeG2lmvfKld2azk8lk/36L/cnkZDbDIT3Sp4DZ8QS9dTI57tNDTwJOOu+4j/0TvDQz+QXMSG+7mUn+sZBZQELnNROcKhMZBXx+gS4k8+IzTpmBXAJOnqPxTDzPFRKyCODuvSKPgwwC2EZ+lxf4E4xwCzhBU7PBPQx4BWR88+fwDgNGAbMsM9/Ec8bygE3A5966L3nOlhiZBGSf+l2YggGLgBna1DMsE4FBQH9zvw1HLEgX0Evkt5GeEVIFMFztpJF6rZQm4DNasVDSEkKSgIVN/ibP0ZwoEgQsfPTPSZgH8QIG8vYr4gdBrIABvf2K2EEQKWBQb78ichBECRhE8O8SlQ5iBAQvcffFPhoYQoSAAQ5/TcQ0CBYw0OGvCZ4GoQIGF/3bhGaDQAELvfKhERgIwgQMePrPCQsEQQLwFwYPmksiQMCC1n1iCFgooQtYwLJfPPQFQ7KAUfU/wABVwMj6TzdAFDDY6tcOMR3SBIyw/1QDJAGj7D/RAEXA6Oa/hhIHCAJG23+SAb+AEfefYsArYET1nwlvTegVgBONFnTDik8ATjNi0BEbHgGjuP5147k6dgsYaQHQxF0OOAUMfv2LhnOVzCVg4OufdFwrpS4BePkSgA6ZcAhYggCocQRCu4ClCIAaeyC0CliaAKCwhgGrALxwaUC3OtgELFEAUNjCgEXAklQAdSzVgEUAXrRUoGstzAKWbgJIzJPAKGAJJ4DEOAmMAvCCpQPda2ASsJQTQGKa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", + } + + TriggerEvent("esx_phone:addSpecialContact", specialContact.name, specialContact.number, specialContact.base64Icon) + end) + end + + if Config.Blip.show then + CreateThread(function() + local blip = AddBlipForCoord(Config.Zones.ShopEntering.Pos) + + SetBlipSprite(blip, Config.Blip.Sprite) + SetBlipDisplay(blip, Config.Blip.Display) + SetBlipScale(blip, Config.Blip.Scale) + SetBlipAsShortRange(blip, true) + + BeginTextCommandSetBlipName("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("car_dealer")) + EndTextCommandSetBlipName(blip) + end) + end + + return true end local function PlayerManagement() - if not Config.EnablePlayerManagement then - return true - end - - if LocalPlayer.state.job ~= "cardealer" then - Config.Zones.ShopEntering.Type = -1 - Config.Zones.BossActions.Type = -1 - Config.Zones.ResellVehicle.Type = -1 - return true - end - Config.Zones.ShopEntering.Type = 1 - - if LocalPlayer.state.job.grade_name == "boss" then - Config.Zones.BossActions.Type = 1 - end - return true + if not Config.EnablePlayerManagement then + return true + end + + if LocalPlayer.state.job ~= "cardealer" then + Config.Zones.ShopEntering.Type = -1 + Config.Zones.BossActions.Type = -1 + Config.Zones.ResellVehicle.Type = -1 + return true + end + Config.Zones.ShopEntering.Type = 1 + + if LocalPlayer.state.job.grade_name == "boss" then + Config.Zones.BossActions.Type = 1 + end + return true end local function loadIpl() - RequestIpl("shr_int") + RequestIpl("shr_int") - local interiorID = 7170 - PinInteriorInMemory(interiorID) - ActivateInteriorEntitySet(interiorID, "csr_beforeMission") - RefreshInterior(interiorID) + local interiorID = 7170 + PinInteriorInMemory(interiorID) + ActivateInteriorEntitySet(interiorID, "csr_beforeMission") + RefreshInterior(interiorID) end RegisterNetEvent("esx:playerLoaded") AddEventHandler("esx:playerLoaded", function(xPlayer) - Init() - PlayerManagement() - CreateThread(loadIpl) + Init() + PlayerManagement() + CreateThread(loadIpl) end) RegisterNetEvent("esx:setJob", PlayerManagement) local function DeleteDisplayVehicleInsideShop() - local attempt = 0 - - if currentDisplayVehicle and DoesEntityExist(currentDisplayVehicle) then - while - DoesEntityExist(currentDisplayVehicle) - and not NetworkHasControlOfEntity(currentDisplayVehicle) - and attempt < 100 - do - Wait(100) - NetworkRequestControlOfEntity(currentDisplayVehicle) - attempt = attempt + 1 - end - - if DoesEntityExist(currentDisplayVehicle) and NetworkHasControlOfEntity(currentDisplayVehicle) then - ESX.Game.DeleteVehicle(currentDisplayVehicle) - end - end + local attempt = 0 + + if currentDisplayVehicle and DoesEntityExist(currentDisplayVehicle) then + while DoesEntityExist(currentDisplayVehicle) and not NetworkHasControlOfEntity(currentDisplayVehicle) and attempt < 100 do + Wait(100) + NetworkRequestControlOfEntity(currentDisplayVehicle) + attempt = attempt + 1 + end + + if DoesEntityExist(currentDisplayVehicle) and NetworkHasControlOfEntity(currentDisplayVehicle) then + ESX.Game.DeleteVehicle(currentDisplayVehicle) + end + end end local function ReturnVehicleProvider() - local elements = { - { - unselectable = true, - icon = "fas fa-car", - title = TranslateCap("car_dealer"), - }, - } - - for k, v in ipairs(cardealerVehicles) do - local returnPrice = ESX.Math.Round(v.price * 0.75) - local vehicleLabel = getVehicleFromModel(v.vehicle).label - - TableInsert(elements, { - title = ('%s [%s]'):format( - vehicleLabel, - TranslateCap("generic_shopitem", ESX.Math.GroupDigits(returnPrice)) - ), - name = v.vehicle, - }) - end - - ESX.OpenContext("right", elements, function(menu, element) - if not element.name then - return ESX.CloseContext() - end - TriggerServerEvent("esx_vehicleshop:returnProvider", element.name) - Wait(500) - ESX.CloseContext() - ReturnVehicleProvider() - end, function(menu) end) + local elements = { + { + unselectable = true, + icon = "fas fa-car", + title = TranslateCap("car_dealer"), + }, + } + + for k, v in ipairs(cardealerVehicles) do + local returnPrice = ESX.Math.Round(v.price * 0.75) + local vehicleLabel = getVehicleFromModel(v.vehicle).label + + TableInsert(elements, { + title = ('%s [%s]'):format(vehicleLabel, TranslateCap("generic_shopitem", ESX.Math.GroupDigits(returnPrice))), + name = v.vehicle, + }) + end + + ESX.OpenContext("right", elements, function(menu, element) + if not element.name then + return ESX.CloseContext() + end + TriggerServerEvent("esx_vehicleshop:returnProvider", element.name) + Wait(500) + ESX.CloseContext() + ReturnVehicleProvider() + end, function(menu) end) end local function StartShopRestriction() - while IsInShopMenu do - Wait(0) + while IsInShopMenu do + Wait(0) - DisableControlAction(0, 75, true) -- Disable exit vehicle - DisableControlAction(27, 75, true) -- Disable exit vehicle - end + DisableControlAction(0, 75, true) -- Disable exit vehicle + DisableControlAction(27, 75, true) -- Disable exit vehicle + end end local function WaitForVehicleToLoad(modelHash) - modelHash = (type(modelHash) == "number" and modelHash or joaat(modelHash)) + modelHash = (type(modelHash) == "number" and modelHash or joaat(modelHash)) - if not HasModelLoaded(modelHash) then - RequestModel(modelHash) + if not HasModelLoaded(modelHash) then + RequestModel(modelHash) - BeginTextCommandBusyspinnerOn("STRING") - AddTextComponentSubstringPlayerName(TranslateCap("shop_awaiting_model")) - EndTextCommandBusyspinnerOn(4) + BeginTextCommandBusyspinnerOn("STRING") + AddTextComponentSubstringPlayerName(TranslateCap("shop_awaiting_model")) + EndTextCommandBusyspinnerOn(4) - while not HasModelLoaded(modelHash) do - Wait(0) - DisableAllControlActions(0) - end + while not HasModelLoaded(modelHash) do + Wait(0) + DisableAllControlActions(0) + end - BusyspinnerOff() - end + BusyspinnerOff() + end end local function OpenShopMenu() - if #Vehicles == 0 then - print("[^3ERROR^7] Vehicleshop has ^50^7 vehicles, please add some!") - return - end - - IsInShopMenu = true - - CreateThread(StartShopRestriction) - ESX.UI.Menu.CloseAll() - ESX.CloseContext() - - local playerPed = ESX.PlayerData.ped - - FreezeEntityPosition(playerPed, true) - SetEntityVisible(playerPed, false) - SetEntityCoords(playerPed, Config.Zones.ShopInside.Pos) - - local elements = {} - local firstVehicleData = nil - - for i = 1, #Categories, 1 do - local category = Categories[i] - local categoryVehicles = vehiclesByCategory[category.name] - local options = {} - - for j = 1, #categoryVehicles, 1 do - local vehicle = categoryVehicles[j] - - if i == 1 and j == 1 then - firstVehicleData = vehicle - end - - TableInsert( - options, - ('%s %s'):format( - vehicle.name, - TranslateCap("generic_shopitem", ESX.Math.GroupDigits(vehicle.price)) - ) - ) - end - - table.sort(options) - - TableInsert(elements, { - name = category.name, - label = category.label, - value = 0, - type = "slider", - max = #Categories[i], - options = options, - }) - end - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "vehicle_shop", { - title = TranslateCap("car_dealer"), - align = "top-left", - elements = elements, - }, function(data, menu) - local vehicleData = vehiclesByCategory[data.current.name][data.current.value + 1] - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "shop_confirm", { - title = TranslateCap("buy_vehicle_shop", vehicleData.name, ESX.Math.GroupDigits(vehicleData.price)), - align = "top-left", - elements = { - { label = TranslateCap("no"), value = "no" }, - { label = TranslateCap("yes"), value = "yes" }, - }, - }, function(data2, menu2) - if data2.current.value == "yes" then - if Config.EnablePlayerManagement then - ESX.TriggerServerCallback("esx_vehicleshop:buyCarDealerVehicle", function(success) - if success then - IsInShopMenu = false - DeleteDisplayVehicleInsideShop() - - CurrentAction = "shop_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - - local playerPed = ESX.PlayerData.ped - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) - - menu2.close() - menu.close() - ESX.ShowNotification(TranslateCap("vehicle_purchased")) - else - ESX.ShowNotification(TranslateCap("broke_company")) - end - end, vehicleData.model) - else - local generatedPlate = GeneratePlate() - - ESX.TriggerServerCallback("esx_vehicleshop:buyVehicle", function(success) - if success then - IsInShopMenu = false - menu2.close() - menu.close() - DeleteDisplayVehicleInsideShop() - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - else - ESX.ShowNotification(TranslateCap("not_enough_money")) - end - end, vehicleData.model, generatedPlate) - end - else - menu2.close() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - menu.close() - DeleteDisplayVehicleInsideShop() - local playerPed = ESX.PlayerData.ped - - CurrentAction = "shop_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) - - IsInShopMenu = false - end, function(data, menu) - local vehicleData = vehiclesByCategory[data.current.name][data.current.value + 1] - local playerPed = ESX.PlayerData.ped - - DeleteDisplayVehicleInsideShop() - WaitForVehicleToLoad(vehicleData.model) - - ESX.Game.SpawnLocalVehicle( - vehicleData.model, - Config.Zones.ShopInside.Pos, - Config.Zones.ShopInside.Heading, - function(vehicle) - currentDisplayVehicle = vehicle - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(vehicleData.model) - end - ) - end) - - DeleteDisplayVehicleInsideShop() - WaitForVehicleToLoad(firstVehicleData.model) - - ESX.Game.SpawnLocalVehicle( - firstVehicleData.model, - Config.Zones.ShopInside.Pos, - Config.Zones.ShopInside.Heading, - function(vehicle) - currentDisplayVehicle = vehicle - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(firstVehicleData.model) - end - ) + if #Vehicles == 0 then + print("[^3ERROR^7] Vehicleshop has ^50^7 vehicles, please add some!") + return + end + + IsInShopMenu = true + + CreateThread(StartShopRestriction) + ESX.UI.Menu.CloseAll() + ESX.CloseContext() + + local playerPed = ESX.PlayerData.ped + + FreezeEntityPosition(playerPed, true) + SetEntityVisible(playerPed, false) + SetEntityCoords(playerPed, Config.Zones.ShopInside.Pos) + + local elements = {} + local firstVehicleData = nil + + for i = 1, #Categories, 1 do + local category = Categories[i] + local categoryVehicles = vehiclesByCategory[category.name] + local options = {} + + for j = 1, #categoryVehicles, 1 do + local vehicle = categoryVehicles[j] + + if i == 1 and j == 1 then + firstVehicleData = vehicle + end + + TableInsert(options, ('%s %s'):format(vehicle.name, TranslateCap("generic_shopitem", ESX.Math.GroupDigits(vehicle.price)))) + end + + table.sort(options) + + TableInsert(elements, { + name = category.name, + label = category.label, + value = 0, + type = "slider", + max = #Categories[i], + options = options, + }) + end + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "vehicle_shop", { + title = TranslateCap("car_dealer"), + align = "top-left", + elements = elements, + }, function(data, menu) + local vehicleData = vehiclesByCategory[data.current.name][data.current.value + 1] + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "shop_confirm", { + title = TranslateCap("buy_vehicle_shop", vehicleData.name, ESX.Math.GroupDigits(vehicleData.price)), + align = "top-left", + elements = { + { label = TranslateCap("no"), value = "no" }, + { label = TranslateCap("yes"), value = "yes" }, + }, + }, function(data2, menu2) + if data2.current.value == "yes" then + if Config.EnablePlayerManagement then + ESX.TriggerServerCallback("esx_vehicleshop:buyCarDealerVehicle", function(success) + if success then + IsInShopMenu = false + DeleteDisplayVehicleInsideShop() + + CurrentAction = "shop_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + + local playerPed = ESX.PlayerData.ped + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) + + menu2.close() + menu.close() + ESX.ShowNotification(TranslateCap("vehicle_purchased")) + else + ESX.ShowNotification(TranslateCap("broke_company")) + end + end, vehicleData.model) + else + local generatedPlate = GeneratePlate() + + ESX.TriggerServerCallback("esx_vehicleshop:buyVehicle", function(success) + if success then + IsInShopMenu = false + menu2.close() + menu.close() + DeleteDisplayVehicleInsideShop() + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + else + ESX.ShowNotification(TranslateCap("not_enough_money")) + end + end, vehicleData.model, generatedPlate) + end + else + menu2.close() + end + end, function(data2, menu2) + menu2.close() + end) + end, function(data, menu) + menu.close() + DeleteDisplayVehicleInsideShop() + local playerPed = ESX.PlayerData.ped + + CurrentAction = "shop_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) + + IsInShopMenu = false + end, function(data, menu) + local vehicleData = vehiclesByCategory[data.current.name][data.current.value + 1] + local playerPed = ESX.PlayerData.ped + + DeleteDisplayVehicleInsideShop() + WaitForVehicleToLoad(vehicleData.model) + + ESX.Game.SpawnLocalVehicle(vehicleData.model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle) + currentDisplayVehicle = vehicle + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(vehicleData.model) + end) + end) + + DeleteDisplayVehicleInsideShop() + WaitForVehicleToLoad(firstVehicleData.model) + + ESX.Game.SpawnLocalVehicle(firstVehicleData.model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle) + currentDisplayVehicle = vehicle + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(firstVehicleData.model) + end) end function OpenResellerMenu() - ESX.UI.Menu.CloseAll() - ESX.CloseContext() - - local elements = { - { unselectable = true, icon = "fas fa-car", title = TranslateCap("car_dealer") }, - { title = TranslateCap("buy_vehicle"), name = "buy_vehicle" }, - { title = TranslateCap("pop_vehicle"), name = "pop_vehicle" }, - { title = TranslateCap("depop_vehicle"), name = "depop_vehicle" }, - { title = TranslateCap("return_provider"), name = "return_provider" }, - { title = TranslateCap("create_bill"), name = "create_bill" }, - { title = TranslateCap("get_rented_vehicles"), name = "get_rented_vehicles" }, - { title = TranslateCap("set_vehicle_owner_sell"), name = "set_vehicle_owner_sell" }, - { title = TranslateCap("set_vehicle_owner_rent"), name = "set_vehicle_owner_rent" }, - { title = TranslateCap("deposit_stock"), name = "put_stock" }, - { title = TranslateCap("take_stock"), name = "get_stock" }, - } - - ESX.OpenContext("right", elements, function(menu, element) - local action = element.name - - if Config.OxInventory and (action == "put_stock" or action == "get_stock") then - exports.ox_inventory:openInventory("stash", "society_cardealer") - elseif action == "buy_vehicle" then - OpenShopMenu() - elseif action == "put_stock" then - OpenPutStocksMenu() - elseif action == "get_stock" then - OpenGetStocksMenu() - elseif action == "pop_vehicle" then - OpenPopVehicleMenu() - elseif action == "depop_vehicle" then - if currentDisplayVehicle then - DeleteDisplayVehicleInsideShop() - else - ESX.ShowNotification(TranslateCap("no_current_vehicle")) - end - elseif action == "return_provider" then - ReturnVehicleProvider() - elseif action == "create_bill" then - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer ~= -1 and closestDistance < 3 then - ESX.CloseContext() - ESX.OpenContext( - "right", - { - { - title = TranslateCap("invoice_amount"), - input = true, - inputType = "number", - inputValue = 0, - inputMin = 0, - name = "invoice_amount", - }, - }, - function(menu2, element2) - if element2.name == "invoice_amount" then - local amount = tonumber(element2.inputValue) - if amount ~= nil then - ESX.CloseContext() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - if closestPlayer == -1 or closestDistance > 3.0 then - ESX.ShowNotification(TranslateCap("no_players")) - else - TriggerServerEvent( - "esx_billing:sendBill", - GetPlayerServerId(closestPlayer), - "society_cardealer", - TranslateCap("car_dealer"), - amount - ) - end - end - end - end, - function(menu) end - ) - else - ESX.ShowNotification(TranslateCap("no_players")) - end - elseif action == "get_rented_vehicles" then - OpenRentedVehiclesMenu() - elseif action == "set_vehicle_owner_sell" then - if currentDisplayVehicle then - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - - if closestPlayer ~= -1 and closestDistance < 3 then - local newPlate = GeneratePlate() - local vehicleProps = ESX.Game.GetVehicleProperties(currentDisplayVehicle) - vehicleProps.plate = newPlate - SetVehicleNumberPlateText(currentDisplayVehicle, newPlate) - TriggerServerEvent( - "esx_vehicleshop:setVehicleOwnedPlayerId", - GetPlayerServerId(closestPlayer), - vehicleProps, - CurrentVehicleData.model, - CurrentVehicleData.name - ) - currentDisplayVehicle = nil - else - ESX.ShowNotification(TranslateCap("no_players")) - end - else - ESX.ShowNotification(TranslateCap("no_current_vehicle")) - end - elseif action == "set_vehicle_owner_rent" then - if currentDisplayVehicle then - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - - if closestPlayer ~= -1 and closestDistance < 3 then - ESX.UI.Menu.Open("dialog", GetCurrentResourceName(), "set_vehicle_owner_rent_amount", { - title = TranslateCap("rental_amount"), - }, function(data2, menu2) - local amount = tonumber(data2.value) - - if not amount then - ESX.ShowNotification(TranslateCap("invalid_amount")) - else - menu2.close() - local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() - - if closestPlayer ~= -1 and closestDistance < 3 then - local newPlate = "RENT" .. string.upper(ESX.GetRandomString(4)) - local model = CurrentVehicleData.model - SetVehicleNumberPlateText(currentDisplayVehicle, newPlate) - TriggerServerEvent( - "esx_vehicleshop:rentVehicle", - model, - newPlate, - amount, - GetPlayerServerId(closestPlayer) - ) - currentDisplayVehicle = nil - else - ESX.ShowNotification(TranslateCap("no_players")) - end - end - end, function(data2, menu2) - menu2.close() - end) - else - ESX.ShowNotification(TranslateCap("no_players")) - end - else - ESX.ShowNotification(TranslateCap("no_current_vehicle")) - end - end - end, function(menu) - CurrentAction = "reseller_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - end) + ESX.UI.Menu.CloseAll() + ESX.CloseContext() + + local elements = { + { unselectable = true, icon = "fas fa-car", title = TranslateCap("car_dealer") }, + { title = TranslateCap("buy_vehicle"), name = "buy_vehicle" }, + { title = TranslateCap("pop_vehicle"), name = "pop_vehicle" }, + { title = TranslateCap("depop_vehicle"), name = "depop_vehicle" }, + { title = TranslateCap("return_provider"), name = "return_provider" }, + { title = TranslateCap("create_bill"), name = "create_bill" }, + { title = TranslateCap("get_rented_vehicles"), name = "get_rented_vehicles" }, + { title = TranslateCap("set_vehicle_owner_sell"), name = "set_vehicle_owner_sell" }, + { title = TranslateCap("set_vehicle_owner_rent"), name = "set_vehicle_owner_rent" }, + { title = TranslateCap("deposit_stock"), name = "put_stock" }, + { title = TranslateCap("take_stock"), name = "get_stock" }, + } + + ESX.OpenContext("right", elements, function(menu, element) + local action = element.name + + if Config.OxInventory and (action == "put_stock" or action == "get_stock") then + exports.ox_inventory:openInventory("stash", "society_cardealer") + elseif action == "buy_vehicle" then + OpenShopMenu() + elseif action == "put_stock" then + OpenPutStocksMenu() + elseif action == "get_stock" then + OpenGetStocksMenu() + elseif action == "pop_vehicle" then + OpenPopVehicleMenu() + elseif action == "depop_vehicle" then + if currentDisplayVehicle then + DeleteDisplayVehicleInsideShop() + else + ESX.ShowNotification(TranslateCap("no_current_vehicle")) + end + elseif action == "return_provider" then + ReturnVehicleProvider() + elseif action == "create_bill" then + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer ~= -1 and closestDistance < 3 then + ESX.CloseContext() + ESX.OpenContext("right", { + { + title = TranslateCap("invoice_amount"), + input = true, + inputType = "number", + inputValue = 0, + inputMin = 0, + name = "invoice_amount", + }, + }, function(menu2, element2) + if element2.name == "invoice_amount" then + local amount = tonumber(element2.inputValue) + if amount ~= nil then + ESX.CloseContext() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + if closestPlayer == -1 or closestDistance > 3.0 then + ESX.ShowNotification(TranslateCap("no_players")) + else + TriggerServerEvent("bpt_billing:sendBill", GetPlayerServerId(closestPlayer), "society_cardealer", TranslateCap("car_dealer"), amount) + end + end + end + end, function(menu) end) + else + ESX.ShowNotification(TranslateCap("no_players")) + end + elseif action == "get_rented_vehicles" then + OpenRentedVehiclesMenu() + elseif action == "set_vehicle_owner_sell" then + if currentDisplayVehicle then + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + + if closestPlayer ~= -1 and closestDistance < 3 then + local newPlate = GeneratePlate() + local vehicleProps = ESX.Game.GetVehicleProperties(currentDisplayVehicle) + vehicleProps.plate = newPlate + SetVehicleNumberPlateText(currentDisplayVehicle, newPlate) + TriggerServerEvent("esx_vehicleshop:setVehicleOwnedPlayerId", GetPlayerServerId(closestPlayer), vehicleProps, CurrentVehicleData.model, CurrentVehicleData.name) + currentDisplayVehicle = nil + else + ESX.ShowNotification(TranslateCap("no_players")) + end + else + ESX.ShowNotification(TranslateCap("no_current_vehicle")) + end + elseif action == "set_vehicle_owner_rent" then + if currentDisplayVehicle then + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + + if closestPlayer ~= -1 and closestDistance < 3 then + ESX.UI.Menu.Open("dialog", GetCurrentResourceName(), "set_vehicle_owner_rent_amount", { + title = TranslateCap("rental_amount"), + }, function(data2, menu2) + local amount = tonumber(data2.value) + + if not amount then + ESX.ShowNotification(TranslateCap("invalid_amount")) + else + menu2.close() + local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() + + if closestPlayer ~= -1 and closestDistance < 3 then + local newPlate = "RENT" .. string.upper(ESX.GetRandomString(4)) + local model = CurrentVehicleData.model + SetVehicleNumberPlateText(currentDisplayVehicle, newPlate) + TriggerServerEvent("esx_vehicleshop:rentVehicle", model, newPlate, amount, GetPlayerServerId(closestPlayer)) + currentDisplayVehicle = nil + else + ESX.ShowNotification(TranslateCap("no_players")) + end + end + end, function(data2, menu2) + menu2.close() + end) + else + ESX.ShowNotification(TranslateCap("no_players")) + end + else + ESX.ShowNotification(TranslateCap("no_current_vehicle")) + end + end + end, function(menu) + CurrentAction = "reseller_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + end) end function OpenPopVehicleMenu() - local elements = {} - - for k, v in ipairs(cardealerVehicles) do - local vehicleLabel = getVehicleFromModel(v.vehicle).label - - TableInsert(elements, { - label = ('%s [%s]'):format( - vehicleLabel, - TranslateCap("generic_shopitem", ESX.Math.GroupDigits(v.price)) - ), - value = v.vehicle, - }) - end - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "commercial_vehicles", { - title = TranslateCap("vehicle_dealer"), - align = "top-left", - elements = elements, - }, function(data, menu) - local model = data.current.value - DeleteDisplayVehicleInsideShop() - - ESX.Game.SpawnVehicle(model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle) - currentDisplayVehicle = vehicle - - for i = 1, #Vehicles, 1 do - if model == Vehicles[i].model then - CurrentVehicleData = Vehicles[i] - break - end - end - end) - end, function(data, menu) - menu.close() - end) + local elements = {} + + for k, v in ipairs(cardealerVehicles) do + local vehicleLabel = getVehicleFromModel(v.vehicle).label + + TableInsert(elements, { + label = ('%s [%s]'):format(vehicleLabel, TranslateCap("generic_shopitem", ESX.Math.GroupDigits(v.price))), + value = v.vehicle, + }) + end + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "commercial_vehicles", { + title = TranslateCap("vehicle_dealer"), + align = "top-left", + elements = elements, + }, function(data, menu) + local model = data.current.value + DeleteDisplayVehicleInsideShop() + + ESX.Game.SpawnVehicle(model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle) + currentDisplayVehicle = vehicle + + for i = 1, #Vehicles, 1 do + if model == Vehicles[i].model then + CurrentVehicleData = Vehicles[i] + break + end + end + end) + end, function(data, menu) + menu.close() + end) end function OpenRentedVehiclesMenu() - local elements = {} - - for k, v in ipairs(rentedVehicles) do - local vehicleLabel = getVehicleFromModel(v.name).label - - TableInsert(elements, { - label = ('%s: %s - %s'):format(v.playerName, vehicleLabel, v.plate), - value = v.name, - }) - end - - ESX.UI.Menu.Open( - "default", - GetCurrentResourceName(), - "rented_vehicles", - { - title = TranslateCap("rent_vehicle"), - align = "top-left", - elements = elements, - }, - nil, - function(data, menu) - menu.close() - end - ) + local elements = {} + + for k, v in ipairs(rentedVehicles) do + local vehicleLabel = getVehicleFromModel(v.name).label + + TableInsert(elements, { + label = ('%s: %s - %s'):format(v.playerName, vehicleLabel, v.plate), + value = v.name, + }) + end + + ESX.UI.Menu.Open( + "default", + GetCurrentResourceName(), + "rented_vehicles", + { + title = TranslateCap("rent_vehicle"), + align = "top-left", + elements = elements, + }, + nil, + function(data, menu) + menu.close() + end + ) end local function OpenBossActionsMenu() - ESX.UI.Menu.CloseAll() - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "reseller", { - title = TranslateCap("dealer_boss"), - align = "top-left", - elements = { - { label = TranslateCap("boss_actions"), value = "boss_actions" }, - { label = TranslateCap("boss_sold"), value = "sold_vehicles" }, - }, - }, function(data, menu) - if data.current.value == "boss_actions" then - TriggerEvent("esx_society:openBossMenu", "cardealer", function(data2, menu2) - menu2.close() - end) - elseif data.current.value == "sold_vehicles" then - local elements = { - head = { - TranslateCap("customer_client"), - TranslateCap("customer_model"), - TranslateCap("customer_plate"), - TranslateCap("customer_soldby"), - TranslateCap("customer_date"), - }, - rows = {}, - } - - for i = 1, #soldVehicles, 1 do - TableInsert(elements.rows, { - data = soldVehicles[i], - cols = { - soldVehicles[i].client, - soldVehicles[i].model, - soldVehicles[i].plate, - soldVehicles[i].soldby, - soldVehicles[i].date, - }, - }) - end - - ESX.UI.Menu.Open( - "list", - GetCurrentResourceName(), - "sold_vehicles", - elements, - function(data2, menu2) end, - function(data2, menu2) - menu2.close() - end - ) - end - end, function(data, menu) - menu.close() - - CurrentAction = "boss_actions_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - end) + ESX.UI.Menu.CloseAll() + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "reseller", { + title = TranslateCap("dealer_boss"), + align = "top-left", + elements = { + { label = TranslateCap("boss_actions"), value = "boss_actions" }, + { label = TranslateCap("boss_sold"), value = "sold_vehicles" }, + }, + }, function(data, menu) + if data.current.value == "boss_actions" then + TriggerEvent("esx_society:openBossMenu", "cardealer", function(data2, menu2) + menu2.close() + end) + elseif data.current.value == "sold_vehicles" then + local elements = { + head = { + TranslateCap("customer_client"), + TranslateCap("customer_model"), + TranslateCap("customer_plate"), + TranslateCap("customer_soldby"), + TranslateCap("customer_date"), + }, + rows = {}, + } + + for i = 1, #soldVehicles, 1 do + TableInsert(elements.rows, { + data = soldVehicles[i], + cols = { + soldVehicles[i].client, + soldVehicles[i].model, + soldVehicles[i].plate, + soldVehicles[i].soldby, + soldVehicles[i].date, + }, + }) + end + + ESX.UI.Menu.Open("list", GetCurrentResourceName(), "sold_vehicles", elements, function(data2, menu2) end, function(data2, menu2) + menu2.close() + end) + end + end, function(data, menu) + menu.close() + + CurrentAction = "boss_actions_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + end) end function OpenGetStocksMenu() - ESX.TriggerServerCallback("esx_vehicleshop:getStockItems", function(items) - local elements = {} - - for i = 1, #items, 1 do - if items[i].count > 0 then - TableInsert(elements, { - label = "x" .. items[i].count .. " " .. items[i].label, - value = items[i].name, - }) - end - end - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "stocks_menu", { - title = TranslateCap("dealership_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 = TranslateCap("amount"), - }, function(data2, menu2) - local count = tonumber(data2.value) - - if count == nil then - ESX.ShowNotification(TranslateCap("quantity_invalid")) - else - TriggerServerEvent("esx_vehicleshop:getStockItem", itemName, count) - menu2.close() - menu.close() - OpenGetStocksMenu() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - menu.close() - end) - end) + ESX.TriggerServerCallback("esx_vehicleshop:getStockItems", function(items) + local elements = {} + + for i = 1, #items, 1 do + if items[i].count > 0 then + TableInsert(elements, { + label = "x" .. items[i].count .. " " .. items[i].label, + value = items[i].name, + }) + end + end + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "stocks_menu", { + title = TranslateCap("dealership_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 = TranslateCap("amount"), + }, function(data2, menu2) + local count = tonumber(data2.value) + + if count == nil then + ESX.ShowNotification(TranslateCap("quantity_invalid")) + else + TriggerServerEvent("esx_vehicleshop:getStockItem", itemName, count) + menu2.close() + menu.close() + OpenGetStocksMenu() + end + end, function(data2, menu2) + menu2.close() + end) + end, function(data, menu) + menu.close() + end) + end) end function OpenPutStocksMenu() - ESX.TriggerServerCallback("esx_vehicleshop:getPlayerInventory", function(inventory) - local elements = {} - - for i = 1, #inventory.items, 1 do - local item = inventory.items[i] - - if item.count > 0 then - TableInsert(elements, { - label = item.label .. " x" .. item.count, - type = "item_standard", - value = item.name, - }) - end - end - - ESX.UI.Menu.Open("default", GetCurrentResourceName(), "stocks_menu", { - title = TranslateCap("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 = TranslateCap("amount"), - }, function(data2, menu2) - local count = tonumber(data2.value) - - if count == nil then - ESX.ShowNotification(TranslateCap("quantity_invalid")) - else - TriggerServerEvent("esx_vehicleshop:putStockItems", itemName, count) - menu2.close() - menu.close() - OpenPutStocksMenu() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - menu.close() - end) - end) + ESX.TriggerServerCallback("esx_vehicleshop:getPlayerInventory", function(inventory) + local elements = {} + + for i = 1, #inventory.items, 1 do + local item = inventory.items[i] + + if item.count > 0 then + TableInsert(elements, { + label = item.label .. " x" .. item.count, + type = "item_standard", + value = item.name, + }) + end + end + + ESX.UI.Menu.Open("default", GetCurrentResourceName(), "stocks_menu", { + title = TranslateCap("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 = TranslateCap("amount"), + }, function(data2, menu2) + local count = tonumber(data2.value) + + if count == nil then + ESX.ShowNotification(TranslateCap("quantity_invalid")) + else + TriggerServerEvent("esx_vehicleshop:putStockItems", itemName, count) + menu2.close() + menu.close() + OpenPutStocksMenu() + end + end, function(data2, menu2) + menu2.close() + end) + end, function(data, menu) + menu.close() + end) + end) end local function hasEnteredMarker(zone) - if zone == "ShopEntering" then - if not Config.EnablePlayerManagement then - CurrentAction = "shop_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - end - if LocalPlayer.state.job ~= nil and LocalPlayer.state.job.name == "cardealer" then - CurrentAction = "reseller_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - end - elseif zone == "GiveBackVehicle" and Config.EnablePlayerManagement then - local playerPed = ESX.PlayerData.ped - - if IsPedInAnyVehicle(playerPed, false) then - local vehicle = GetVehiclePedIsIn(playerPed, false) - - CurrentAction = "give_back_vehicle" - CurrentActionMsg = TranslateCap("vehicle_menu") - CurrentActionData = { vehicle = vehicle } - end - elseif zone == "ResellVehicle" then - local playerPed = ESX.PlayerData.ped - - if IsPedSittingInAnyVehicle(playerPed) then - local vehicle = GetVehiclePedIsIn(playerPed, false) - local vehicleData, model, resellPrice, plate - - if GetPedInVehicleSeat(vehicle, -1) == playerPed then - for i = 1, #Vehicles, 1 do - if joaat(Vehicles[i].model) == GetEntityModel(vehicle) then - vehicleData = Vehicles[i] - break - end - end - - if vehicleData then - resellPrice = ESX.Math.Round(vehicleData.price / 100 * Config.ResellPercentage) - model = GetEntityModel(vehicle) - plate = ESX.Math.Trim(GetVehicleNumberPlateText(vehicle)) - - CurrentAction = "resell_vehicle" - CurrentActionMsg = TranslateCap("sell_menu", vehicleData.name, ESX.Math.GroupDigits(resellPrice)) - - CurrentActionData = { - vehicle = vehicle, - label = vehicleData.name, - price = resellPrice, - model = model, - plate = plate, - } - else - ESX.ShowNotification(TranslateCap("invalid_vehicle")) - end - end - end - elseif - zone == "BossActions" - and Config.EnablePlayerManagement - and LocalPlayer.state.job ~= nil - and LocalPlayer.state.job.name == "cardealer" - and LocalPlayer.state.job.grade_name == "boss" - then - CurrentAction = "boss_actions_menu" - CurrentActionMsg = TranslateCap("shop_menu") - CurrentActionData = {} - end + if zone == "ShopEntering" then + if not Config.EnablePlayerManagement then + CurrentAction = "shop_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + end + if LocalPlayer.state.job ~= nil and LocalPlayer.state.job.name == "cardealer" then + CurrentAction = "reseller_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + end + elseif zone == "GiveBackVehicle" and Config.EnablePlayerManagement then + local playerPed = ESX.PlayerData.ped + + if IsPedInAnyVehicle(playerPed, false) then + local vehicle = GetVehiclePedIsIn(playerPed, false) + + CurrentAction = "give_back_vehicle" + CurrentActionMsg = TranslateCap("vehicle_menu") + CurrentActionData = { vehicle = vehicle } + end + elseif zone == "ResellVehicle" then + local playerPed = ESX.PlayerData.ped + + if IsPedSittingInAnyVehicle(playerPed) then + local vehicle = GetVehiclePedIsIn(playerPed, false) + local vehicleData, model, resellPrice, plate + + if GetPedInVehicleSeat(vehicle, -1) == playerPed then + for i = 1, #Vehicles, 1 do + if joaat(Vehicles[i].model) == GetEntityModel(vehicle) then + vehicleData = Vehicles[i] + break + end + end + + if vehicleData then + resellPrice = ESX.Math.Round(vehicleData.price / 100 * Config.ResellPercentage) + model = GetEntityModel(vehicle) + plate = ESX.Math.Trim(GetVehicleNumberPlateText(vehicle)) + + CurrentAction = "resell_vehicle" + CurrentActionMsg = TranslateCap("sell_menu", vehicleData.name, ESX.Math.GroupDigits(resellPrice)) + + CurrentActionData = { + vehicle = vehicle, + label = vehicleData.name, + price = resellPrice, + model = model, + plate = plate, + } + else + ESX.ShowNotification(TranslateCap("invalid_vehicle")) + end + end + end + elseif zone == "BossActions" and Config.EnablePlayerManagement and LocalPlayer.state.job ~= nil and LocalPlayer.state.job.name == "cardealer" and LocalPlayer.state.job.grade_name == "boss" then + CurrentAction = "boss_actions_menu" + CurrentActionMsg = TranslateCap("shop_menu") + CurrentActionData = {} + end end local function hasExitedMarker(zone) - if not IsInShopMenu then - ESX.UI.Menu.CloseAll() - ESX.CloseContext() - end - ESX.HideUI() - CurrentAction = nil + if not IsInShopMenu then + ESX.UI.Menu.CloseAll() + ESX.CloseContext() + end + ESX.HideUI() + CurrentAction = nil end AddEventHandler("onResourceStop", function(resource) - if resource ~= GetCurrentResourceName() then - return - end - if IsInShopMenu then - ESX.UI.Menu.CloseAll() - ESX.CloseContext() - - local playerPed = ESX.PlayerData.ped - - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) - end - - ESX.HideUI() - DeleteDisplayVehicleInsideShop() + if resource ~= GetCurrentResourceName() then + return + end + if IsInShopMenu then + ESX.UI.Menu.CloseAll() + ESX.CloseContext() + + local playerPed = ESX.PlayerData.ped + + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos) + end + + ESX.HideUI() + DeleteDisplayVehicleInsideShop() end) -- Enter / Exit marker events & Draw Markers CreateThread(function() - while true do - Wait(0) - local playerCoords = GetEntityCoords(ESX.PlayerData.ped) - local isInMarker, letSleep, currentZone = false, true - - for k, v in pairs(Config.Zones) do - local distance = #(playerCoords - v.Pos) - - if distance < Config.DrawDistance then - letSleep = false - - if v.Type ~= -1 then - DrawMarker( - v.Type, - v.Pos, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - v.Size.x, - v.Size.y, - v.Size.z, - Config.MarkerColor.r, - Config.MarkerColor.g, - Config.MarkerColor.b, - 100, - false, - true, - 2, - false, - nil, - nil, - false - ) - end - - if distance < v.Size.x then - isInMarker, currentZone = true, k - end - end - end - - if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then - HasAlreadyEnteredMarker, LastZone = true, currentZone - LastZone = currentZone - hasEnteredMarker(currentZone) - end - - if not isInMarker and HasAlreadyEnteredMarker then - HasAlreadyEnteredMarker = false - hasExitedMarker(LastZone) - end - - if letSleep then - Wait(1000) - end - end + while true do + Wait(0) + local playerCoords = GetEntityCoords(ESX.PlayerData.ped) + local isInMarker, letSleep, currentZone = false, true + + for k, v in pairs(Config.Zones) do + local distance = #(playerCoords - v.Pos) + + if distance < Config.DrawDistance then + letSleep = false + + if v.Type ~= -1 then + DrawMarker(v.Type, v.Pos, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, nil, nil, false) + end + + if distance < v.Size.x then + isInMarker, currentZone = true, k + end + end + end + + if (isInMarker and not HasAlreadyEnteredMarker) or (isInMarker and LastZone ~= currentZone) then + HasAlreadyEnteredMarker, LastZone = true, currentZone + LastZone = currentZone + hasEnteredMarker(currentZone) + end + + if not isInMarker and HasAlreadyEnteredMarker then + HasAlreadyEnteredMarker = false + hasExitedMarker(LastZone) + end + + if letSleep then + Wait(1000) + end + end end) -- Key controls CreateThread(function() - while true do - Wait(0) - - if CurrentAction then - ESX.TextUI(CurrentActionMsg) - - if IsControlJustReleased(0, 38) then - if CurrentAction == "shop_menu" then - if Config.LicenseEnable then - ESX.TriggerServerCallback("esx_license:checkLicense", function(hasDriversLicense) - if hasDriversLicense then - OpenShopMenu() - else - ESX.ShowNotification(TranslateCap("license_missing")) - end - end, GetPlayerServerId(PlayerId()), "drive") - else - OpenShopMenu() - end - elseif CurrentAction == "reseller_menu" then - OpenResellerMenu() - elseif CurrentAction == "give_back_vehicle" then - ESX.TriggerServerCallback("esx_vehicleshop:giveBackVehicle", function(isRentedVehicle) - if isRentedVehicle then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - ESX.ShowNotification(TranslateCap("delivered")) - else - ESX.ShowNotification(TranslateCap("not_rental")) - end - end, ESX.Math.Trim(GetVehicleNumberPlateText(CurrentActionData.vehicle))) - elseif CurrentAction == "resell_vehicle" then - ESX.TriggerServerCallback("esx_vehicleshop:resellVehicle", function(vehicleSold) - if vehicleSold then - ESX.Game.DeleteVehicle(CurrentActionData.vehicle) - ESX.ShowNotification( - TranslateCap( - "vehicle_sold_for", - CurrentActionData.label, - ESX.Math.GroupDigits(CurrentActionData.price) - ) - ) - else - ESX.ShowNotification(TranslateCap("not_yours")) - end - end, CurrentActionData.plate, CurrentActionData.model) - elseif CurrentAction == "boss_actions_menu" then - OpenBossActionsMenu() - end - ESX.HideUI() - CurrentAction = nil - end - else - Wait(1000) - end - end + while true do + Wait(0) + + if CurrentAction then + ESX.TextUI(CurrentActionMsg) + + if IsControlJustReleased(0, 38) then + if CurrentAction == "shop_menu" then + if Config.LicenseEnable then + ESX.TriggerServerCallback("esx_license:checkLicense", function(hasDriversLicense) + if hasDriversLicense then + OpenShopMenu() + else + ESX.ShowNotification(TranslateCap("license_missing")) + end + end, GetPlayerServerId(PlayerId()), "drive") + else + OpenShopMenu() + end + elseif CurrentAction == "reseller_menu" then + OpenResellerMenu() + elseif CurrentAction == "give_back_vehicle" then + ESX.TriggerServerCallback("esx_vehicleshop:giveBackVehicle", function(isRentedVehicle) + if isRentedVehicle then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + ESX.ShowNotification(TranslateCap("delivered")) + else + ESX.ShowNotification(TranslateCap("not_rental")) + end + end, ESX.Math.Trim(GetVehicleNumberPlateText(CurrentActionData.vehicle))) + elseif CurrentAction == "resell_vehicle" then + ESX.TriggerServerCallback("esx_vehicleshop:resellVehicle", function(vehicleSold) + if vehicleSold then + ESX.Game.DeleteVehicle(CurrentActionData.vehicle) + ESX.ShowNotification(TranslateCap("vehicle_sold_for", CurrentActionData.label, ESX.Math.GroupDigits(CurrentActionData.price))) + else + ESX.ShowNotification(TranslateCap("not_yours")) + end + end, CurrentActionData.plate, CurrentActionData.model) + elseif CurrentAction == "boss_actions_menu" then + OpenBossActionsMenu() + end + ESX.HideUI() + CurrentAction = nil + end + else + Wait(1000) + end + end end) if ESX.PlayerLoaded then - PlayerManagement() + PlayerManagement() end