From 355c04bebbffffc848ae7e9da76ca35d182f6196 Mon Sep 17 00:00:00 2001 From: ElPumpo Date: Fri, 24 Jan 2020 13:25:10 +0100 Subject: [PATCH] Move vehicle garage to seperate file, see desc for full change --- client/main.lua | 367 ++------------------------------------------- client/vehicle.lua | 322 +++++++++++++++++++++++++++++++++++++++ config.lua | 84 +++++------ fxmanifest.lua | 3 +- locales/br.lua | 4 +- locales/de.lua | 4 +- locales/en.lua | 4 +- locales/es.lua | 4 +- locales/fi.lua | 4 +- locales/fr.lua | 4 +- locales/ko.lua | 4 +- locales/pl.lua | 4 +- locales/sv.lua | 8 +- server/main.lua | 27 +--- 14 files changed, 398 insertions(+), 445 deletions(-) create mode 100644 client/vehicle.lua diff --git a/client/main.lua b/client/main.lua index d5ef5c40..e2d024f5 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,7 +1,6 @@ -local PlayerData, CurrentActionData, handcuffTimer, dragStatus, blipsCops, currentTask, spawnedVehicles = {}, {}, {}, {}, {}, {}, {} -local HasAlreadyEnteredMarker, isDead, isHandcuffed, hasAlreadyJoined, playerInService, isInShopMenu = false, false, false, false, false, false +local CurrentActionData, handcuffTimer, dragStatus, blipsCops, currentTask = {}, {}, {}, {}, {} local LastStation, LastPart, LastPartNum, LastEntity, CurrentAction, CurrentActionMsg -dragStatus.isDragged = false +dragStatus.isDragged, isInShopMenu = false, false ESX = nil Citizen.CreateThread(function() @@ -14,7 +13,7 @@ Citizen.CreateThread(function() Citizen.Wait(10) end - PlayerData = ESX.GetPlayerData() + ESX.PlayerData = ESX.GetPlayerData() end) function cleanPlayer(playerPed) @@ -49,7 +48,7 @@ end function OpenCloakroomMenu() local playerPed = PlayerPedId() - local grade = PlayerData.job.grade_name + local grade = ESX.PlayerData.job.grade_name local elements = { {label = _U('citizen_wear'), value = 'citizen_wear'}, @@ -230,346 +229,6 @@ function OpenArmoryMenu(station) end) end -function OpenVehicleSpawnerMenu(type, station, part, partNum) - local playerCoords = GetEntityCoords(PlayerPedId()) - PlayerData = ESX.GetPlayerData() - local elements = { - {label = _U('garage_storeditem'), action = 'garage'}, - {label = _U('garage_storeitem'), action = 'store_garage'}, - {label = _U('garage_buyitem'), action = 'buy_vehicle'} - } - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle', { - title = _U('garage_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - if data.current.action == 'buy_vehicle' then - local shopElements, shopCoords = {} - - if type == 'car' then - shopCoords = Config.PoliceStations[station].Vehicles[partNum].InsideShop - local authorizedVehicles = Config.AuthorizedVehicles[PlayerData.job.grade_name] - - if #Config.AuthorizedVehicles.Shared > 0 then - for k,vehicle in ipairs(Config.AuthorizedVehicles.Shared) do - table.insert(shopElements, { - label = ('%s - %s'):format(vehicle.label, _U('shop_item', ESX.Math.GroupDigits(vehicle.price))), - name = vehicle.label, - model = vehicle.model, - price = vehicle.price, - type = 'car' - }) - end - end - - if #authorizedVehicles > 0 then - for k,vehicle in ipairs(authorizedVehicles) do - table.insert(shopElements, { - label = ('%s - %s'):format(vehicle.label, _U('shop_item', ESX.Math.GroupDigits(vehicle.price))), - name = vehicle.label, - model = vehicle.model, - price = vehicle.price, - type = 'car' - }) - end - else - if #Config.AuthorizedVehicles.Shared == 0 then - return - end - end - elseif type == 'helicopter' then - shopCoords = Config.PoliceStations[station].Helicopters[partNum].InsideShop - local authorizedHelicopters = Config.AuthorizedHelicopters[PlayerData.job.grade_name] - - if #authorizedHelicopters > 0 then - for k,vehicle in ipairs(authorizedHelicopters) do - table.insert(shopElements, { - label = ('%s - %s'):format(vehicle.label, _U('shop_item', ESX.Math.GroupDigits(vehicle.price))), - name = vehicle.label, - model = vehicle.model, - price = vehicle.price, - livery = vehicle.livery or nil, - type = 'helicopter' - }) - end - else - ESX.ShowNotification(_U('helicopter_notauthorized')) - return - end - end - - OpenShopMenu(shopElements, playerCoords, shopCoords) - elseif data.current.action == 'garage' then - local garage = {} - - ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles) - if #jobVehicles > 0 then - for k,v in ipairs(jobVehicles) do - local props = json.decode(v.vehicle) - local vehicleName = GetLabelText(GetDisplayNameFromVehicleModel(props.model)) - local label = ('%s - %s: '):format(vehicleName, props.plate) - - if v.stored then - label = label .. ('%s'):format(_U('garage_stored')) - else - label = label .. ('%s'):format(_U('garage_notstored')) - end - - table.insert(garage, { - label = label, - stored = v.stored, - model = props.model, - vehicleProps = props - }) - end - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_garage', { - title = _U('garage_title'), - align = 'top-left', - elements = garage - }, function(data2, menu2) - if data2.current.stored then - local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(station, part, partNum) - - if foundSpawn then - menu2.close() - - ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) - ESX.Game.SetVehicleProperties(vehicle, data2.current.vehicleProps) - - TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.vehicleProps.plate, false) - ESX.ShowNotification(_U('garage_released')) - end) - end - else - ESX.ShowNotification(_U('garage_notavailable')) - end - end, function(data2, menu2) - menu2.close() - end) - else - ESX.ShowNotification(_U('garage_empty')) - end - end, type) - elseif data.current.action == 'store_garage' then - StoreNearbyVehicle(playerCoords) - end - end, function(data, menu) - menu.close() - end) -end - -function StoreNearbyVehicle(playerCoords) - local vehicles, vehiclePlates = ESX.Game.GetVehiclesInArea(playerCoords, 30.0), {} - - if #vehicles > 0 then - for k,v in ipairs(vehicles) do - - -- Make sure the vehicle we're saving is empty, or else it wont be deleted - if GetVehicleNumberOfPassengers(v) == 0 and IsVehicleSeatFree(v, -1) then - table.insert(vehiclePlates, { - vehicle = v, - plate = ESX.Math.Trim(GetVehicleNumberPlateText(v)) - }) - end - end - else - ESX.ShowNotification(_U('garage_store_nearby')) - return - end - - ESX.TriggerServerCallback('esx_policejob:storeNearbyVehicle', function(storeSuccess, foundNum) - if storeSuccess then - local vehicleId = vehiclePlates[foundNum] - local attempts = 0 - ESX.Game.DeleteVehicle(vehicleId.vehicle) - IsBusy = true - - Citizen.CreateThread(function() - BeginTextCommandBusyspinnerOn('STRING') - AddTextComponentSubstringPlayerName(_U('garage_storing')) - EndTextCommandBusyspinnerOn(4) - - while IsBusy do - Citizen.Wait(100) - end - - BusyspinnerOff() - end) - - -- Workaround for vehicle not deleting when other players are near it. - while DoesEntityExist(vehicleId.vehicle) do - Citizen.Wait(500) - attempts = attempts + 1 - - -- Give up - if attempts > 30 then - break - end - - vehicles = ESX.Game.GetVehiclesInArea(playerCoords, 30.0) - if #vehicles > 0 then - for k,v in ipairs(vehicles) do - if ESX.Math.Trim(GetVehicleNumberPlateText(v)) == vehicleId.plate then - ESX.Game.DeleteVehicle(v) - break - end - end - end - end - - IsBusy = false - ESX.ShowNotification(_U('garage_has_stored')) - else - ESX.ShowNotification(_U('garage_has_notstored')) - end - end, vehiclePlates) -end - -function GetAvailableVehicleSpawnPoint(station, part, partNum) - local spawnPoints = Config.PoliceStations[station][part][partNum].SpawnPoints - local found, foundSpawnPoint = false, nil - - for i=1, #spawnPoints, 1 do - if ESX.Game.IsSpawnPointClear(spawnPoints[i].coords, spawnPoints[i].radius) then - found, foundSpawnPoint = true, spawnPoints[i] - break - end - end - - if found then - return true, foundSpawnPoint - else - ESX.ShowNotification(_U('vehicle_blocked')) - return false - end -end - -function OpenShopMenu(elements, restoreCoords, shopCoords) - local playerPed = PlayerPedId() - isInShopMenu = true - - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop', { - title = _U('vehicleshop_title'), - align = 'top-left', - elements = elements - }, function(data, menu) - ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop_confirm', { - title = _U('vehicleshop_confirm', data.current.name, data.current.price), - align = 'top-left', - elements = { - {label = _U('confirm_no'), value = 'no'}, - {label = _U('confirm_yes'), value = 'yes'} - }}, function(data2, menu2) - if data2.current.value == 'yes' then - local newPlate = exports['esx_vehicleshop']:GeneratePlate() - local vehicle = GetVehiclePedIsIn(playerPed, false) - local props = ESX.Game.GetVehicleProperties(vehicle) - props.plate = newPlate - - ESX.TriggerServerCallback('esx_policejob:buyJobVehicle', function (bought) - if bought then - ESX.ShowNotification(_U('vehicleshop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price))) - - isInShopMenu = false - ESX.UI.Menu.CloseAll() - DeleteSpawnedVehicles() - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - - ESX.Game.Teleport(playerPed, restoreCoords) - else - ESX.ShowNotification(_U('vehicleshop_money')) - menu2.close() - end - end, props, data.current.type) - else - menu2.close() - end - end, function(data2, menu2) - menu2.close() - end) - end, function(data, menu) - isInShopMenu = false - ESX.UI.Menu.CloseAll() - - DeleteSpawnedVehicles() - FreezeEntityPosition(playerPed, false) - SetEntityVisible(playerPed, true) - - ESX.Game.Teleport(playerPed, restoreCoords) - end, function(data, menu) - DeleteSpawnedVehicles() - WaitForVehicleToLoad(data.current.model) - - ESX.Game.SpawnLocalVehicle(data.current.model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(data.current.model) - - if data.current.livery then - SetVehicleModKit(vehicle, 0) - SetVehicleLivery(vehicle, data.current.livery) - end - end) - end) - - WaitForVehicleToLoad(elements[1].model) - ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle) - table.insert(spawnedVehicles, vehicle) - TaskWarpPedIntoVehicle(playerPed, vehicle, -1) - FreezeEntityPosition(vehicle, true) - SetModelAsNoLongerNeeded(elements[1].model) - - if elements[1].livery then - SetVehicleModKit(vehicle, 0) - SetVehicleLivery(vehicle, elements[1].livery) - end - end) -end - -Citizen.CreateThread(function() - while true do - Citizen.Wait(0) - - if isInShopMenu then - DisableControlAction(0, 75, true) -- Disable exit vehicle - DisableControlAction(27, 75, true) -- Disable exit vehicle - else - Citizen.Wait(500) - end - end -end) - -function DeleteSpawnedVehicles() - while #spawnedVehicles > 0 do - local vehicle = spawnedVehicles[1] - ESX.Game.DeleteVehicle(vehicle) - table.remove(spawnedVehicles, 1) - end -end - -function WaitForVehicleToLoad(modelHash) - modelHash = (type(modelHash) == 'number' and modelHash or GetHashKey(modelHash)) - - if not HasModelLoaded(modelHash) then - RequestModel(modelHash) - - BeginTextCommandBusyspinnerOn('STRING') - AddTextComponentSubstringPlayerName(_U('vehicleshop_awaiting_model')) - EndTextCommandBusyspinnerOn(4) - - while not HasModelLoaded(modelHash) do - Citizen.Wait(0) - DisableAllControlActions(0) - end - - BusyspinnerOff() - end -end - function OpenPoliceActionsMenu() ESX.UI.Menu.CloseAll() @@ -1041,7 +700,7 @@ function OpenBuyWeaponsMenu() local playerPed = PlayerPedId() PlayerData = ESX.GetPlayerData() - for k,v in ipairs(Config.AuthorizedWeapons[PlayerData.job.grade_name]) do + for k,v in ipairs(Config.AuthorizedWeapons[ESX.PlayerData.job.grade_name]) do local weaponNum, weapon = ESX.GetWeapon(v.weapon) local components, label = {} local hasWeapon = HasPedGotWeapon(playerPed, GetHashKey(v.weapon), false) @@ -1244,7 +903,7 @@ end RegisterNetEvent('esx:setJob') AddEventHandler('esx:setJob', function(job) - PlayerData.job = job + ESX.PlayerData.job = job Citizen.Wait(5000) TriggerServerEvent('esx_policejob:forceBlip') @@ -1263,7 +922,7 @@ end) -- don't show dispatches if the player isn't in service AddEventHandler('esx_phone:cancelMessage', function(dispatchNumber) - if PlayerData.job and PlayerData.job.name == 'police' and PlayerData.job.name == dispatchNumber then + 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() @@ -1306,7 +965,7 @@ end) AddEventHandler('esx_policejob:hasEnteredEntityZone', function(entity) local playerPed = PlayerPedId() - if PlayerData.job and PlayerData.job.name == 'police' and IsPedOnFoot(playerPed) then + if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' and IsPedOnFoot(playerPed) then CurrentAction = 'remove_entity' CurrentActionMsg = _U('remove_prop') CurrentActionData = {entity = entity} @@ -1553,7 +1212,7 @@ Citizen.CreateThread(function() while true do Citizen.Wait(0) - if PlayerData.job and PlayerData.job.name == 'police' then + if ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local isInMarker, hasExited, letSleep = false, false, true @@ -1612,7 +1271,7 @@ Citizen.CreateThread(function() end end - if Config.EnablePlayerManagement and PlayerData.job.grade_name == 'boss' then + if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == 'boss' then for i=1, #v.BossActions, 1 do local distance = #(playerCoords - v.BossActions[i]) @@ -1714,7 +1373,7 @@ Citizen.CreateThread(function() if CurrentAction then ESX.ShowHelpNotification(CurrentActionMsg) - if IsControlJustReleased(0, 38) and PlayerData.job and PlayerData.job.name == 'police' then + if IsControlJustReleased(0, 38) and ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' then if CurrentAction == 'menu_cloakroom' then OpenCloakroomMenu() @@ -1761,7 +1420,7 @@ Citizen.CreateThread(function() end end -- CurrentAction end - if IsControlJustReleased(0, 167) and not isDead and PlayerData.job and PlayerData.job.name == 'police' and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions') then + if IsControlJustReleased(0, 167) and not isDead and ESX.PlayerData.job and ESX.PlayerData.job.name == 'police' and not ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'police_actions') then if not Config.EnableESXService then OpenPoliceActionsMenu() elseif playerInService then @@ -1820,7 +1479,7 @@ AddEventHandler('esx_policejob:updateBlip', function() end -- Is the player a cop? In that case show all the blips for other cops - if PlayerData.job and PlayerData.job.name == 'police' then + 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 diff --git a/client/vehicle.lua b/client/vehicle.lua new file mode 100644 index 00000000..a0af0aec --- /dev/null +++ b/client/vehicle.lua @@ -0,0 +1,322 @@ + +local spawnedVehicles = {} + +function OpenVehicleSpawnerMenu(type, station, part, partNum) + local playerCoords = GetEntityCoords(PlayerPedId()) + + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle', { + title = _U('garage_title'), + align = 'top-left', + elements = { + {label = _U('garage_storeditem'), action = 'garage'}, + {label = _U('garage_storeitem'), action = 'store_garage'}, + {label = _U('garage_buyitem'), action = 'buy_vehicle'} + }}, function(data, menu) + if data.current.action == 'buy_vehicle' then + local shopElements = {} + local shopCoords = Config.PoliceStations[station][part][partNum].InsideShop + local authorizedVehicles = Config.AuthorizedVehicles[type][ESX.PlayerData.job.grade_name] + + if #authorizedVehicles > 0 then + for k,vehicle in ipairs(authorizedVehicles) do + if IsModelInCdimage(vehicle.model) then + local vehicleLabel = GetLabelText(GetDisplayNameFromVehicleModel(vehicle.model)) + + table.insert(shopElements, { + label = ('%s - %s'):format(vehicleLabel, _U('shop_item', ESX.Math.GroupDigits(vehicle.price))), + name = vehicleLabel, + model = vehicle.model, + price = vehicle.price, + props = vehicle.props, + type = type + }) + end + end + + if #shopElements > 0 then + OpenShopMenu(shopElements, playerCoords, shopCoords) + else + ESX.ShowNotification(_U('garage_notauthorized')) + end + else + ESX.ShowNotification(_U('garage_notauthorized')) + end + elseif data.current.action == 'garage' then + local garage = {} + + ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles) + if #jobVehicles > 0 then + local allVehicleProps = {} + + for k,v in ipairs(jobVehicles) do + local props = json.decode(v.vehicle) + + if IsModelInCdimage(props.model) then + local vehicleName = GetLabelText(GetDisplayNameFromVehicleModel(props.model)) + local label = ('%s - %s: '):format(vehicleName, props.plate) + + if v.stored then + label = label .. ('%s'):format(_U('garage_stored')) + else + label = label .. ('%s'):format(_U('garage_notstored')) + end + + table.insert(garage, { + label = label, + stored = v.stored, + model = props.model, + plate = props.plate + }) + + allVehicleProps[props.plate] = props + end + end + + if #garage > 0 then + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_garage', { + title = _U('garage_title'), + align = 'top-left', + elements = garage + }, function(data2, menu2) + if data2.current.stored then + local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(station, part, partNum) + + if foundSpawn then + menu2.close() + + ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle) + local vehicleProps = allVehicleProps[data2.current.plate] + ESX.Game.SetVehicleProperties(vehicle, vehicleProps) + + TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.plate, false) + ESX.ShowNotification(_U('garage_released')) + end) + end + else + ESX.ShowNotification(_U('garage_notavailable')) + end + end, function(data2, menu2) + menu2.close() + end) + else + ESX.ShowNotification(_U('garage_empty')) + end + else + ESX.ShowNotification(_U('garage_empty')) + end + end, type) + elseif data.current.action == 'store_garage' then + StoreNearbyVehicle(playerCoords) + end + end, function(data, menu) + menu.close() + end) +end + +function StoreNearbyVehicle(playerCoords) + local vehicles, vehiclePlates = ESX.Game.GetVehiclesInArea(playerCoords, 30.0), {} + + if #vehicles > 0 then + for k,v in ipairs(vehicles) do + + -- Make sure the vehicle we're saving is empty, or else it wont be deleted + if GetVehicleNumberOfPassengers(v) == 0 and IsVehicleSeatFree(v, -1) then + table.insert(vehiclePlates, { + vehicle = v, + plate = ESX.Math.Trim(GetVehicleNumberPlateText(v)) + }) + end + end + else + ESX.ShowNotification(_U('garage_store_nearby')) + return + end + + ESX.TriggerServerCallback('esx_policejob:storeNearbyVehicle', function(storeSuccess, foundNum) + if storeSuccess then + local vehicleId = vehiclePlates[foundNum] + local attempts = 0 + ESX.Game.DeleteVehicle(vehicleId.vehicle) + IsBusy = true + + Citizen.CreateThread(function() + BeginTextCommandBusyspinnerOn('STRING') + AddTextComponentSubstringPlayerName(_U('garage_storing')) + EndTextCommandBusyspinnerOn(4) + + while IsBusy do + Citizen.Wait(100) + end + + BusyspinnerOff() + end) + + -- Workaround for vehicle not deleting when other players are near it. + while DoesEntityExist(vehicleId.vehicle) do + Citizen.Wait(500) + attempts = attempts + 1 + + -- Give up + if attempts > 30 then + break + end + + vehicles = ESX.Game.GetVehiclesInArea(playerCoords, 30.0) + if #vehicles > 0 then + for k,v in ipairs(vehicles) do + if ESX.Math.Trim(GetVehicleNumberPlateText(v)) == vehicleId.plate then + ESX.Game.DeleteVehicle(v) + break + end + end + end + end + + IsBusy = false + ESX.ShowNotification(_U('garage_has_stored')) + else + ESX.ShowNotification(_U('garage_has_notstored')) + end + end, vehiclePlates) +end + +function GetAvailableVehicleSpawnPoint(station, part, partNum) + local spawnPoints = Config.PoliceStations[station][part][partNum].SpawnPoints + local found, foundSpawnPoint = false, nil + + for i=1, #spawnPoints, 1 do + if ESX.Game.IsSpawnPointClear(spawnPoints[i].coords, spawnPoints[i].radius) then + found, foundSpawnPoint = true, spawnPoints[i] + break + end + end + + if found then + return true, foundSpawnPoint + else + ESX.ShowNotification(_U('vehicle_blocked')) + return false + end +end + +function OpenShopMenu(elements, restoreCoords, shopCoords) + local playerPed = PlayerPedId() + isInShopMenu = true + + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop', { + title = _U('vehicleshop_title'), + align = 'top-left', + elements = elements + }, function(data, menu) + ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop_confirm', { + title = _U('vehicleshop_confirm', data.current.name, data.current.price), + align = 'top-left', + elements = { + {label = _U('confirm_no'), value = 'no'}, + {label = _U('confirm_yes'), value = 'yes'} + }}, function(data2, menu2) + if data2.current.value == 'yes' then + local newPlate = exports['esx_vehicleshop']:GeneratePlate() + local vehicle = GetVehiclePedIsIn(playerPed, false) + local props = ESX.Game.GetVehicleProperties(vehicle) + props.plate = newPlate + + ESX.TriggerServerCallback('esx_policejob:buyJobVehicle', function (bought) + if bought then + ESX.ShowNotification(_U('vehicleshop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price))) + + isInShopMenu = false + ESX.UI.Menu.CloseAll() + DeleteSpawnedVehicles() + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + + ESX.Game.Teleport(playerPed, restoreCoords) + else + ESX.ShowNotification(_U('vehicleshop_money')) + menu2.close() + end + end, props, data.current.type) + else + menu2.close() + end + end, function(data2, menu2) + menu2.close() + end) + end, function(data, menu) + isInShopMenu = false + ESX.UI.Menu.CloseAll() + + DeleteSpawnedVehicles() + FreezeEntityPosition(playerPed, false) + SetEntityVisible(playerPed, true) + + ESX.Game.Teleport(playerPed, restoreCoords) + end, function(data, menu) + DeleteSpawnedVehicles() + WaitForVehicleToLoad(data.current.model) + + ESX.Game.SpawnLocalVehicle(data.current.model, shopCoords, 0.0, function(vehicle) + table.insert(spawnedVehicles, vehicle) + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(data.current.model) + + if data.current.props then + ESX.Game.SetVehicleProperties(vehicle, data.current.props) + end + end) + end) + + WaitForVehicleToLoad(elements[1].model) + ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle) + table.insert(spawnedVehicles, vehicle) + TaskWarpPedIntoVehicle(playerPed, vehicle, -1) + FreezeEntityPosition(vehicle, true) + SetModelAsNoLongerNeeded(elements[1].model) + + if elements[1].props then + ESX.Game.SetVehicleProperties(vehicle, elements[1].props) + end + end) +end + +Citizen.CreateThread(function() + while true do + Citizen.Wait(0) + + if isInShopMenu then + DisableControlAction(0, 75, true) -- Disable exit vehicle + DisableControlAction(27, 75, true) -- Disable exit vehicle + else + Citizen.Wait(500) + end + end +end) + +function DeleteSpawnedVehicles() + while #spawnedVehicles > 0 do + local vehicle = spawnedVehicles[1] + ESX.Game.DeleteVehicle(vehicle) + table.remove(spawnedVehicles, 1) + end +end + +function WaitForVehicleToLoad(modelHash) + modelHash = (type(modelHash) == 'number' and modelHash or GetHashKey(modelHash)) + + if not HasModelLoaded(modelHash) then + RequestModel(modelHash) + + BeginTextCommandBusyspinnerOn('STRING') + AddTextComponentSubstringPlayerName(_U('vehicleshop_awaiting_model')) + EndTextCommandBusyspinnerOn(4) + + while not HasModelLoaded(modelHash) do + Citizen.Wait(0) + DisableAllControlActions(0) + end + + BusyspinnerOff() + end +end diff --git a/config.lua b/config.lua index a47eaa62..f3de61a0 100644 --- a/config.lua +++ b/config.lua @@ -144,65 +144,53 @@ Config.AuthorizedWeapons = { } Config.AuthorizedVehicles = { - Shared = { - {model = 'police', label = 'Police Cruiser', price = 10000}, - {model = 'pbus', label = 'Police Prison Bus', price = 5000} + car = { + recruit = {}, + + officer = { + {model = 'police3', price = 20000} + }, + + sergeant = { + {model = 'policet', price = 18500}, + {model = 'policeb', price = 30500} + }, + + intendent = {}, + + lieutenant = { + {model = 'riot', price = 70000}, + {model = 'fbi2', price = 60000} + }, + + chef = {}, + + boss = {} }, - recruit = { + helicopter = { + recruit = {}, - }, + officer = {}, - officer = { - {model = 'police3', label = 'Police Interceptor', price = 20000} - }, + sergeant = {}, - sergeant = { - {model = 'policet', label = 'Police Transporter', price = 18500}, - {model = 'policeb', label = 'Police Bike', price = 30500} - }, + intendent = {}, - intendent = { + lieutenant = { + {model = 'polmav', props = {modLivery = 0}, price = 200000} + }, - }, - - lieutenant = { - {model = 'riot', label = 'Police Riot', price = 70000}, - {model = 'fbi2', label = 'FIB SUV', price = 60000} - }, - - chef = { - - }, - - boss = { + chef = { + {model = 'polmav', props = {modLivery = 0}, price = 150000} + }, + boss = { + {model = 'polmav', props = {modLivery = 0}, price = 100000} + } } } -Config.AuthorizedHelicopters = { - recruit = {}, - - officer = {}, - - sergeant = {}, - - intendent = {}, - - lieutenant = { - {model = 'polmav', label = 'Police Maverick', livery = 0, price = 200000} - }, - - chef = { - {model = 'polmav', label = 'Police Maverick', livery = 0, price = 150000} - }, - - boss = { - {model = 'polmav', label = 'Police Maverick', livery = 0, price = 100000} - } -} - - Config.CustomPeds = { shared = { {label = 'Sheriff Ped', maleModel = 's_m_y_sheriff_01', femaleModel = 's_f_y_sheriff_01'}, diff --git a/fxmanifest.lua b/fxmanifest.lua index 85852ca4..af5949ca 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -34,7 +34,8 @@ client_scripts { 'locales/sv.lua', 'locales/ko.lua', 'config.lua', - 'client/main.lua' + 'client/main.lua', + 'client/vehicle.lua' } dependencies { diff --git a/locales/br.lua b/locales/br.lua index 13ad287c..e47dda49 100644 --- a/locales/br.lua +++ b/locales/br.lua @@ -20,7 +20,7 @@ Locales['br'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['br'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/de.lua b/locales/de.lua index eb6ee554..7492e226 100644 --- a/locales/de.lua +++ b/locales/de.lua @@ -20,7 +20,7 @@ Locales['de'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['de'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/en.lua b/locales/en.lua index 323f4e7d..0a30a598 100644 --- a/locales/en.lua +++ b/locales/en.lua @@ -20,7 +20,7 @@ Locales['en'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['en'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/es.lua b/locales/es.lua index c9c05cc5..354c89e6 100644 --- a/locales/es.lua +++ b/locales/es.lua @@ -20,7 +20,7 @@ Locales['es'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['es'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/fi.lua b/locales/fi.lua index 93c8af21..b0f5d7d9 100644 --- a/locales/fi.lua +++ b/locales/fi.lua @@ -20,7 +20,7 @@ Locales['fi'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['fi'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/fr.lua b/locales/fr.lua index 8f3071cc..d30a825b 100644 --- a/locales/fr.lua +++ b/locales/fr.lua @@ -20,7 +20,7 @@ Locales['fr'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armurerie - Acheter une arme', ['armory_componenttitle'] = 'armurerie - Accessoires d\'armes', - ['armory_bought'] = 'vous achetez un ~y~%s~s~ pour ~r~$%s~s~', + ['armory_bought'] = 'vous achetez un ~y~%s~s~ pour ~g~$%s~s~', ['armory_money'] = 'vous ne pouvez pas acheter cette arme', ['armory_hascomponent'] = 'vous avez cet accessoire équipé!', ['get_weapon_menu'] = 'armurerie - Retirer arme', @@ -43,8 +43,8 @@ Locales['fr'] = { ['garage_storeditem'] = 'ouvrir le garage', ['garage_storeitem'] = 'ranger le véhicule', ['garage_buyitem'] = 'magasin véhicule', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'appuyez sur ~INPUT_CONTEXT~ pour accéder aux ~y~Actions de l\'hélicoptère~s~.', - ['helicopter_notauthorized'] = 'vous n\'êtes pas autorisé à acheter un hélicoptère.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'magasin véhicule', ['vehicleshop_confirm'] = 'voulez-vous acheter ce véhicule?', diff --git a/locales/ko.lua b/locales/ko.lua index cf7fe418..ea2c093c 100644 --- a/locales/ko.lua +++ b/locales/ko.lua @@ -20,7 +20,7 @@ Locales['ko'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = '병기고 - 무기 구매', ['armory_componenttitle'] = '병기고 - 무기 부착물', - ['armory_bought'] = '당신은 ~r~$%s~s~에 ~y~%s~s~를 구매했습니다', + ['armory_bought'] = '당신은 ~g~$%s~s~에 ~y~%s~s~를 구매했습니다', ['armory_money'] = '당신은 이 무기를 살 수 없습니다', ['armory_hascomponent'] = '이 부착물이 장착되어 있습니다!', ['get_weapon_menu'] = '병기고 - 무기 빼다', @@ -43,8 +43,8 @@ Locales['ko'] = { ['garage_storeditem'] = '차고 열기', ['garage_storeitem'] = '차량 정리', ['garage_buyitem'] = '차량 상점', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = '~y~헬리콥터 동작~s~에 액세스하려면 ~INPUT_CONTEXT~를 누릅니다.', - ['helicopter_notauthorized'] = '헬리콥터를 구매할 수 없습니다.', ['shop_item'] = '$%s', ['vehicleshop_title'] = '차량 판매점', ['vehicleshop_confirm'] = '이 차량을 사고 싶습니까?', diff --git a/locales/pl.lua b/locales/pl.lua index 210092ca..ab5e8678 100644 --- a/locales/pl.lua +++ b/locales/pl.lua @@ -20,7 +20,7 @@ Locales['pl'] = { ['armory_item'] = '$%s', ['armory_weapontitle'] = 'armory - Buy weapon', ['armory_componenttitle'] = 'armory - Weapon attatchments', - ['armory_bought'] = 'you bought an ~y~%s~s~ for ~r~$%s~s~', + ['armory_bought'] = 'you bought an ~y~%s~s~ for ~g~$%s~s~', ['armory_money'] = 'you cannot afford that weapon', ['armory_hascomponent'] = 'you have that attatchment equiped!', ['get_weapon_menu'] = 'armory - Withdraw Weapon', @@ -43,8 +43,8 @@ Locales['pl'] = { ['garage_storeditem'] = 'open garage', ['garage_storeitem'] = 'store vehicle in garage', ['garage_buyitem'] = 'vehicle shop', + ['garage_notauthorized'] = 'you\'re not authorized to buy this kind of vehicles.', ['helicopter_prompt'] = 'press ~INPUT_CONTEXT~ to access the ~y~Helicopter Actions~s~.', - ['helicopter_notauthorized'] = 'you\'re not authorized to buy helicopters.', ['shop_item'] = '$%s', ['vehicleshop_title'] = 'vehicle Shop', ['vehicleshop_confirm'] = 'do you want to buy this vehicle?', diff --git a/locales/sv.lua b/locales/sv.lua index a79aef07..04f52ed0 100644 --- a/locales/sv.lua +++ b/locales/sv.lua @@ -43,12 +43,12 @@ Locales['sv'] = { ['garage_storeditem'] = 'öppna garage', ['garage_storeitem'] = 'ställ in fordon', ['garage_buyitem'] = 'fordonshandel', - ['helicopter_prompt'] = 'klicka på ~INPUT_CONTEXT~ för att komma åt ~y~garaget~s~.', - ['helicopter_notauthorized'] = 'du har inte behörighet till att köpa en helikopter.', + ['garage_notauthorized'] = 'du har inte tillgång till att köpa dessa fordon.', + ['helicopter_prompt'] = 'tryck ~INPUT_CONTEXT~ för att komma åt ~y~helikoptergaraget~s~.', ['shop_item'] = '%s SEK', ['vehicleshop_title'] = 'fordonshandel', ['vehicleshop_confirm'] = 'vill du köpa detta fordon?', - ['vehicleshop_bought'] = 'du köpte ~y~%s~s~ för ~r~$%s~s~', + ['vehicleshop_bought'] = 'du köpte ~y~%s~s~ för ~g~%s SEK~s~', ['vehicleshop_money'] = 'du har inte råd med detta fordon', ['vehicleshop_awaiting_model'] = 'fordonet ~g~LADDAS NED OCH LADDAS IN~s~ var god vänta', ['confirm_no'] = 'nej', @@ -76,7 +76,7 @@ Locales['sv'] = { ['unpaid_bills'] = 'se obetalda räkningar', ['license_check'] = 'se licenser', ['license_revoke'] = 'återkalla licenser', - ['license_revoked'] = 'Ditt ~b~%s~s~ har blivit ~y~återkallat~s~!', + ['license_revoked'] = 'ditt ~b~%s~s~ har blivit ~y~återkallat~s~!', ['licence_you_revoked'] = 'du återkallade ett ~b~%s~s~ som tillhörde ~y~%s~s~', ['no_players_nearby'] = 'det finns ingen i närheten', ['being_searched'] = 'du blir ~y~visiterad~s~ av ~b~Polisen~s~', diff --git a/server/main.lua b/server/main.lua index c30f3fc1..e328e551 100644 --- a/server/main.lua +++ b/server/main.lua @@ -436,29 +436,12 @@ ESX.RegisterServerCallback('esx_policejob:storeNearbyVehicle', function(source, end end) -function getPriceFromHash(hashKey, jobGrade, type) - if type == 'helicopter' then - local vehicles = Config.AuthorizedHelicopters[jobGrade] +function getPriceFromHash(vehicleHash, jobGrade, type) + local vehicles = Config.AuthorizedVehicles[type][jobGrade] - for k,v in ipairs(vehicles) do - if GetHashKey(v.model) == hashKey then - return v.price - end - end - elseif type == 'car' then - local vehicles = Config.AuthorizedVehicles[jobGrade] - local shared = Config.AuthorizedVehicles['Shared'] - - for k,v in ipairs(vehicles) do - if GetHashKey(v.model) == hashKey then - return v.price - end - end - - for k,v in ipairs(shared) do - if GetHashKey(v.model) == hashKey then - return v.price - end + for k,v in ipairs(vehicles) do + if GetHashKey(v.model) == vehicleHash then + return v.price end end