diff --git a/.editorconfig b/.editorconfig index 4bfca33b..ecabf943 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,9 @@ root = true [*] -indent_size = 2 -indent_style = space -end_of_line = lf +indent_size = 4 +indent_style = tab +end_of_line = crlf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true diff --git a/__resource.lua b/__resource.lua index 4d045a9b..758053e8 100644 --- a/__resource.lua +++ b/__resource.lua @@ -2,7 +2,7 @@ resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' description 'ESX Vehicle Shop' -version '1.1.0' +version '1.2.0' server_scripts { '@mysql-async/lib/MySQL.lua', @@ -26,5 +26,6 @@ client_scripts { 'locales/fr.lua', 'locales/sv.lua', 'config.lua', + 'client/utils.lua', 'client/main.lua' } diff --git a/client/main.lua b/client/main.lua index 63f8a844..d22227d0 100644 --- a/client/main.lua +++ b/client/main.lua @@ -419,9 +419,13 @@ function OpenResellerMenu () if closestPlayer == -1 or closestDistance > 3.0 then ESX.ShowNotification(_U('no_players')) else - SetVehicleNumberPlateText(LastVehicles[#LastVehicles], string.upper(ESX.GetRandomString(8))) + + local newPlate = GeneratePlate() local vehicleProps = ESX.Game.GetVehicleProperties(LastVehicles[#LastVehicles]) local model = CurrentVehicleData.model + vehicleProps.plate = newPlate + SetVehicleNumberPlateText(LastVehicles[#LastVehicles], newPlate) + TriggerServerEvent('esx_vehicleshop:sellVehicle', model) @@ -441,10 +445,12 @@ function OpenResellerMenu () ESX.ShowNotification(_U('no_players')) else ESX.TriggerServerCallback('esx:getOtherPlayerData', function (xPlayer) - SetVehicleNumberPlateText(LastVehicles[#LastVehicles], string.upper(ESX.GetRandomString(8))) + local newPlate = GeneratePlate() local vehicleProps = ESX.Game.GetVehicleProperties(LastVehicles[#LastVehicles]) local model = CurrentVehicleData.model - + vehicleProps.plate = newPlate + SetVehicleNumberPlateText(LastVehicles[#LastVehicles], newPlate) + TriggerServerEvent('esx_vehicleshop:sellVehicle', model) if Config.EnableSocietyOwnedVehicles then @@ -476,9 +482,12 @@ function OpenResellerMenu () if closestPlayer == -1 or closestDistance > 5.0 then ESX.ShowNotification(_U('no_players')) else - SetVehicleNumberPlateText(LastVehicles[#LastVehicles], 'RENT' .. string.upper(ESX.GetRandomString(4))) + + local newPlate = 'RENT' .. string.upper(ESX.GetRandomString(4)) local vehicleProps = ESX.Game.GetVehicleProperties(LastVehicles[#LastVehicles]) local model = CurrentVehicleData.model + vehicleProps.plate = newPlate + SetVehicleNumberPlateText(LastVehicles[#LastVehicles], newPlate) TriggerServerEvent('esx_vehicleshop:rentVehicle', model, vehicleProps.plate, GetPlayerName(closestPlayer), CurrentVehicleData.price, amount, GetPlayerServerId(closestPlayer)) diff --git a/client/utils.lua b/client/utils.lua new file mode 100644 index 00000000..ec8992de --- /dev/null +++ b/client/utils.lua @@ -0,0 +1,69 @@ +local NumberCharset = {} +local Charset = {} + +for i = 48, 57 do table.insert(NumberCharset, string.char(i)) end + +for i = 65, 90 do table.insert(Charset, string.char(i)) end +for i = 97, 122 do table.insert(Charset, string.char(i)) end + +function GeneratePlate() + local generatedPlate + local doBreak = false + + while true do + Citizen.Wait(2) + math.randomseed(GetGameTimer()) + if Config.PlateUseSpace then + generatedPlate = string.upper(GetRandomLetter(Config.PlateLetters) .. ' ' .. GetRandomNumber(Config.PlateNumbers)) + else + generatedPlate = string.upper(GetRandomLetter(Config.PlateLetters) .. GetRandomNumber(Config.PlateNumbers)) + end + + ESX.TriggerServerCallback('esx_vehicleshop:isPlateTaken', function (isPlateTaken) + if not isPlateTaken then + doBreak = true + end + end, generatedPlate) + + if doBreak then + break + end + end + + return generatedPlate +end + +-- mixing async with sync tasks +function IsPlateTaken(plate) + local callback = 'waiting' + + ESX.TriggerServerCallback('esx_vehicleshop:isPlateTaken', function (isPlateTaken) + callback = isPlateTaken + end, plate) + + while type(callback) == 'string' do + Citizen.Wait(0) + end + + return callback +end + +function GetRandomNumber(length) + Citizen.Wait(1) + math.randomseed(GetGameTimer()) + if length > 0 then + return GetRandomNumber(length - 1) .. NumberCharset[math.random(1, #NumberCharset)] + else + return '' + end +end + +function GetRandomLetter(length) + Citizen.Wait(1) + math.randomseed(GetGameTimer()) + if length > 0 then + return GetRandomLetter(length - 1) .. Charset[math.random(1, #Charset)] + else + return '' + end +end \ No newline at end of file diff --git a/config.lua b/config.lua index aac0ae8e..8458c0f3 100644 --- a/config.lua +++ b/config.lua @@ -8,6 +8,12 @@ Config.EnableSocietyOwnedVehicles = false Config.ResellPercentage = 50 Config.Locale = 'fr' +-- looks like this: 'LLL NNN' +-- The maximum plate length is 8 chars (including spaces & symbols), don't go past it! +Config.PlateLetters = 3 +Config.PlateNumbers = 3 +Config.PlateUseSpace = true + Config.Zones = { ShopEntering = { diff --git a/locales/en.lua b/locales/en.lua index c395fb23..be12da60 100644 --- a/locales/en.lua +++ b/locales/en.lua @@ -40,10 +40,10 @@ Locales['en'] = { ['shop_menu'] = 'press ~INPUT_CONTEXT~ to access the menu', ['the_boss'] = 'boss', ['vehicle_dealer'] = 'vehicle - Car Dealer', - ['vehicle_menu'] = 'press ~INPUT_CONTEXT~ to make your vehicle', + ['vehicle_menu'] = 'press ~INPUT_CONTEXT~ to give back the rented vehicle', ['vehicle_purchased'] = 'you bought a vehicle', - ['vehicle_set_owned'] = 'Vehicle ~y~%s~s~ has been assigned to ~b~%s~s~', - ['vehicle_set_rented'] = 'Vehicle ~y~%s~s~ has been rented to ~b~%s~s~', + ['vehicle_set_owned'] = 'vehicle ~y~%s~s~ has been assigned to ~b~%s~s~', + ['vehicle_set_rented'] = 'vehicle ~y~%s~s~ has been rented to ~b~%s~s~', ['vehicle_sold'] = 'the vehicle has been ~g~sold~s~', ['vehicle_sold_to'] = 'the vehicle with plate ~y~%s~s~ has been sold to ~b~%s~s~', ['wash_money'] = 'money laundering', diff --git a/server/main.lua b/server/main.lua index 19c4ee3f..e16dc1c2 100644 --- a/server/main.lua +++ b/server/main.lua @@ -31,7 +31,7 @@ function LoadVehicles() for j=1, #Categories, 1 do if Categories[j].name == vehicle.category then vehicle.categoryLabel = Categories[j].label - break --todo confirm + break end end @@ -371,6 +371,14 @@ ESX.RegisterServerCallback('esx_vehicleshop:getPlayerInventory', function (sourc cb({ items = items }) end) +ESX.RegisterServerCallback('esx_vehicleshop:isPlateTaken', function (source, cb, plate) + MySQL.Async.fetchAll('SELECT * FROM owned_vehicles WHERE @plate = plate', { + ['@plate'] = plate + }, function (result) + cb(result[1] ~= nil) + end) +end) + if Config.EnablePvCommand then TriggerEvent('es:addGroupCommand', 'pv', 'user', function(source, args, user) TriggerClientEvent('esx_vehicleshop:openPersonnalVehicleMenu', source)