Major improvements, see desc

- Fixed selling same vehicle multiple times
- Fixed selling <no> vehicle
- Major security improvements
- Removed buying vehicle for society
- Code cleanup
- Fixed depopping vehicle not working (not respecting network owner)
This commit is contained in:
ElPumpo
2020-02-08 12:36:18 +01:00
parent 5e6cd29ca8
commit 14fbc69357
11 changed files with 371 additions and 523 deletions
+13 -5
View File
@@ -1,9 +1,11 @@
# esx_vehicleshop
ESX Vehicle Shop adds an vehicle shop to the game, where employeed players can sell vehicles to other players. You can also disable the job part so any player can buy vehicles with a menu based interaction.
## Requirements
* Auto mode (everyone can buy vehicles from the dealer)
* No need to download another resource
* No need to download other resources
* Player management (the car dealer job): billing, boss actions and more!
* [esx_society](https://github.com/ESX-Org/esx_society)
@@ -15,21 +17,25 @@
## Download & Installation
### Using [fvm](https://github.com/qlaffont/fvm-installer)
```
fvm install --save --folder=esx esx-org/esx_vehicleshop
```
### Using Git
```
cd resources
git clone https://github.com/ESX-Org/esx_vehicleshop [esx]/esx_vehicleshop
```
### Manually
- Download https://github.com/ESX-Org/esx_vehicleshop/archive/master.zip
- Put it in the `[esx]` directory
## Installation
### Installation
- Import `esx_vehicleshop.sql` in your database
- Add this in your `server.cfg`:
@@ -38,14 +44,16 @@ start esx_vehicleshop
```
- If you want player management you have to set `Config.EnablePlayerManagement` to `true` in `config.lua`
# Legal
## Legal
### License
esx_vehicleshop - vehicle shop for ESX
Copyright (C) 2015-2018 Jérémie N'gadi
Copyright (C) 2015-2020 Jérémie N'gadi
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.
You should have received a copy Of the GNU General Public License along with this program. If Not, see http://www.gnu.org/licenses/.
You should have received a copy Of the GNU General Public License along with this program. If Not, see http://www.gnu.org/licenses/.
+156 -261
View File
@@ -6,7 +6,7 @@ local CurrentActionData = {}
local IsInShopMenu = false
local Categories = {}
local Vehicles = {}
local LastVehicles = {}
local currentDisplayVehicle
local CurrentVehicleData
ESX = nil
@@ -42,6 +42,16 @@ Citizen.CreateThread(function()
end
end)
function getVehicleLabelFromModel(model)
for k,v in ipairs(Vehicles) do
if v.model == model then
return v.name
end
end
return
end
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
ESX.PlayerData = xPlayer
@@ -71,26 +81,33 @@ AddEventHandler('esx_vehicleshop:sendVehicles', function(vehicles)
Vehicles = vehicles
end)
function DeleteShopInsideVehicles()
while #LastVehicles > 0 do
local vehicle = LastVehicles[1]
function DeleteDisplayVehicleInsideShop()
local attempt = 0
ESX.Game.DeleteVehicle(vehicle)
table.remove(LastVehicles, 1)
if currentDisplayVehicle and DoesEntityExist(currentDisplayVehicle) then
while DoesEntityExist(currentDisplayVehicle) and not NetworkHasControlOfEntity(currentDisplayVehicle) and attempt < 100 do
Citizen.Wait(100)
NetworkRequestControlOfEntity(currentDisplayVehicle)
attempt = attempt + 1
end
if DoesEntityExist(currentDisplayVehicle) and NetworkHasControlOfEntity(currentDisplayVehicle) then
ESX.Game.DeleteVehicle(currentDisplayVehicle)
end
end
end
function ReturnVehicleProvider()
ESX.TriggerServerCallback('esx_vehicleshop:getCommercialVehicles', function(vehicles)
local elements = {}
local returnPrice
for i=1, #vehicles, 1 do
returnPrice = ESX.Math.Round(vehicles[i].price * 0.75)
for k,v in ipairs(vehicles) do
local returnPrice = ESX.Math.Round(v.price * 0.75)
local vehicleLabel = getVehicleLabelFromModel(v.vehicle)
table.insert(elements, {
label = ('%s [<span style="color:orange;">%s</span>]'):format(vehicles[i].name, _U('generic_shopitem', ESX.Math.GroupDigits(returnPrice))),
value = vehicles[i].name
label = ('%s [<span style="color:orange;">%s</span>]'):format(vehicleLabel, _U('generic_shopitem', ESX.Math.GroupDigits(returnPrice))),
value = v.vehicle
})
end
@@ -145,7 +162,7 @@ function OpenShopMenu()
if IsModelInCdimage(GetHashKey(Vehicles[i].model)) then
table.insert(vehiclesByCategory[Vehicles[i].category], Vehicles[i])
else
print(('esx_vehicleshop: vehicle "%s" does not exist'):format(Vehicles[i].model))
print(('[esx_vehicleshop] [^3ERROR^7] Vehicle "%s" does not exist'):format(Vehicles[i].model))
end
end
@@ -190,147 +207,58 @@ function OpenShopMenu()
}}, function(data2, menu2)
if data2.current.value == 'yes' then
if Config.EnablePlayerManagement then
ESX.TriggerServerCallback('esx_vehicleshop:buyVehicleSociety', function(hasEnoughMoney)
if hasEnoughMoney then
ESX.TriggerServerCallback('esx_vehicleshop:buyCarDealerVehicle', function(success)
if success then
IsInShopMenu = false
DeleteShopInsideVehicles()
local playerPed = PlayerPedId()
DeleteDisplayVehicleInsideShop()
CurrentAction = 'shop_menu'
CurrentActionMsg = _U('shop_menu')
CurrentActionData = {}
local playerPed = PlayerPedId()
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos)
menu2.close()
menu.close()
ESX.ShowNotification(_U('vehicle_purchased'))
else
ESX.ShowNotification(_U('broke_company'))
end
end, 'cardealer', vehicleData.model)
end, vehicleData.model)
else
local playerData = ESX.GetPlayerData()
local generatedPlate = GeneratePlate()
if Config.EnableSocietyOwnedVehicles and playerData.job.grade_name == 'boss' then
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'shop_confirm_buy_type', {
title = _U('purchase_type'),
align = 'top-left',
elements = {
{label = _U('staff_type'), value = 'personnal'},
{label = _U('society_type'), value = 'society'}
}}, function(data3, menu3)
ESX.TriggerServerCallback('esx_vehicleshop:buyVehicle', function(success)
if success then
IsInShopMenu = false
menu2.close()
menu.close()
DeleteDisplayVehicleInsideShop()
if data3.current.value == 'personnal' then
ESX.TriggerServerCallback('esx_vehicleshop:buyVehicle', function(hasEnoughMoney)
if hasEnoughMoney then
IsInShopMenu = false
menu3.close()
menu2.close()
menu.close()
DeleteShopInsideVehicles()
ESX.Game.SpawnVehicle(vehicleData.model, Config.Zones.ShopOutside.Pos, Config.Zones.ShopOutside.Heading, function(vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
local newPlate = GeneratePlate()
local vehicleProps = ESX.Game.GetVehicleProperties(vehicle)
vehicleProps.plate = newPlate
SetVehicleNumberPlateText(vehicle, newPlate)
if Config.EnableOwnedVehicles then
TriggerServerEvent('esx_vehicleshop:setVehicleOwned', vehicleProps)
end
ESX.ShowNotification(_U('vehicle_purchased'))
end)
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
else
ESX.ShowNotification(_U('not_enough_money'))
end
end, vehicleData.model)
elseif data3.current.value == 'society' then
ESX.TriggerServerCallback('esx_vehicleshop:buyVehicleSociety', function(hasEnoughMoney)
if hasEnoughMoney then
IsInShopMenu = false
menu3.close()
menu2.close()
menu.close()
DeleteShopInsideVehicles()
ESX.Game.SpawnVehicle(vehicleData.model, Config.Zones.ShopOutside.Pos, Config.Zones.ShopOutside.Heading, function(vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
local newPlate = GeneratePlate()
local vehicleProps = ESX.Game.GetVehicleProperties(vehicle)
vehicleProps.plate = newPlate
SetVehicleNumberPlateText(vehicle, newPlate)
TriggerServerEvent('esx_vehicleshop:setVehicleOwnedSociety', playerData.job.name, vehicleProps)
ESX.ShowNotification(_U('vehicle_purchased'))
end)
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
else
ESX.ShowNotification(_U('broke_company'))
end
end, playerData.job.name, vehicleData.model)
end
end, function(data3, menu3)
menu3.close()
end)
else
ESX.TriggerServerCallback('esx_vehicleshop:buyVehicle', function(hasEnoughMoney)
if hasEnoughMoney then
IsInShopMenu = false
menu2.close()
menu.close()
DeleteShopInsideVehicles()
ESX.Game.SpawnVehicle(vehicleData.model, Config.Zones.ShopOutside.Pos, Config.Zones.ShopOutside.Heading, function(vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
local newPlate = GeneratePlate()
local vehicleProps = ESX.Game.GetVehicleProperties(vehicle)
vehicleProps.plate = newPlate
SetVehicleNumberPlateText(vehicle, newPlate)
if Config.EnableOwnedVehicles then
TriggerServerEvent('esx_vehicleshop:setVehicleOwned', vehicleProps)
end
ESX.ShowNotification(_U('vehicle_purchased'))
end)
ESX.Game.SpawnVehicle(vehicleData.model, Config.Zones.ShopOutside.Pos, Config.Zones.ShopOutside.Heading, function(vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
SetVehicleNumberPlateText(vehicle, generatedPlate)
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
else
ESX.ShowNotification(_U('not_enough_money'))
end
end, vehicleData.model)
end
end)
else
ESX.ShowNotification(_U('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()
DeleteShopInsideVehicles()
DeleteDisplayVehicleInsideShop()
local playerPed = PlayerPedId()
CurrentAction = 'shop_menu'
@@ -346,22 +274,22 @@ function OpenShopMenu()
local vehicleData = vehiclesByCategory[data.current.name][data.current.value + 1]
local playerPed = PlayerPedId()
DeleteShopInsideVehicles()
DeleteDisplayVehicleInsideShop()
WaitForVehicleToLoad(vehicleData.model)
ESX.Game.SpawnLocalVehicle(vehicleData.model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle)
table.insert(LastVehicles, vehicle)
currentDisplayVehicle = vehicle
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
FreezeEntityPosition(vehicle, true)
SetModelAsNoLongerNeeded(vehicleData.model)
end)
end)
DeleteShopInsideVehicles()
DeleteDisplayVehicleInsideShop()
WaitForVehicleToLoad(firstVehicleData.model)
ESX.Game.SpawnLocalVehicle(firstVehicleData.model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle)
table.insert(LastVehicles, vehicle)
currentDisplayVehicle = vehicle
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
FreezeEntityPosition(vehicle, true)
SetModelAsNoLongerNeeded(firstVehicleData.model)
@@ -374,16 +302,16 @@ function WaitForVehicleToLoad(modelHash)
if not HasModelLoaded(modelHash) then
RequestModel(modelHash)
BeginTextCommandBusyString('STRING')
BeginTextCommandBusyspinnerOn('STRING')
AddTextComponentSubstringPlayerName(_U('shop_awaiting_model'))
EndTextCommandBusyString(4)
EndTextCommandBusyspinnerOn(4)
while not HasModelLoaded(modelHash) do
Citizen.Wait(0)
DisableAllControlActions(0)
end
RemoveLoadingPrompt()
BusyspinnerOff()
end
end
@@ -402,7 +330,6 @@ function OpenResellerMenu()
{label = _U('get_rented_vehicles'), value = 'get_rented_vehicles'},
{label = _U('set_vehicle_owner_sell'), value = 'set_vehicle_owner_sell'},
{label = _U('set_vehicle_owner_rent'), value = 'set_vehicle_owner_rent'},
{label = _U('set_vehicle_owner_sell_society'), value = 'set_vehicle_owner_sell_society'},
{label = _U('deposit_stock'), value = 'put_stock'},
{label = _U('take_stock'), value = 'get_stock'}
}}, function(data, menu)
@@ -417,125 +344,94 @@ function OpenResellerMenu()
elseif action == 'pop_vehicle' then
OpenPopVehicleMenu()
elseif action == 'depop_vehicle' then
DeleteShopInsideVehicles()
if currentDisplayVehicle then
DeleteDisplayVehicleInsideShop()
else
ESX.ShowNotification(_U('no_current_vehicle'))
end
elseif action == 'return_provider' then
ReturnVehicleProvider()
elseif action == 'create_bill' then
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 3.0 then
ESX.ShowNotification(_U('no_players'))
return
end
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'set_vehicle_owner_sell_amount', {
title = _U('invoice_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if closestPlayer ~= -1 and closestDistance < 3 then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'set_vehicle_owner_sell_amount', {
title = _U('invoice_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('invalid_amount'))
else
menu2.close()
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 3.0 then
ESX.ShowNotification(_U('no_players'))
if amount == nil then
ESX.ShowNotification(_U('invalid_amount'))
else
TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_cardealer', _U('car_dealer'), tonumber(data2.value))
end
end
end, function(data2, menu2)
menu2.close()
end)
menu2.close()
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 3.0 then
ESX.ShowNotification(_U('no_players'))
else
TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(closestPlayer), 'society_cardealer', _U('car_dealer'), tonumber(data2.value))
end
end
end, function(data2, menu2)
menu2.close()
end)
else
ESX.ShowNotification(_U('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()
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 3.0 then
ESX.ShowNotification(_U('no_players'))
else
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)
TriggerServerEvent('esx_vehicleshop:addToList', GetPlayerServerId(closestPlayer), model, newPlate)
if Config.EnableOwnedVehicles then
TriggerServerEvent('esx_vehicleshop:setVehicleOwnedPlayerId', GetPlayerServerId(closestPlayer), vehicleProps)
ESX.ShowNotification(_U('vehicle_set_owned', vehicleProps.plate, GetPlayerName(closestPlayer)))
else
ESX.ShowNotification(_U('vehicle_sold_to', vehicleProps.plate, GetPlayerName(closestPlayer)))
end
end
elseif action == 'set_vehicle_owner_sell_society' then
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 3.0 then
ESX.ShowNotification(_U('no_players'))
else
ESX.TriggerServerCallback('esx:getOtherPlayerData', function(xPlayer)
local newPlate = GeneratePlate()
local vehicleProps = ESX.Game.GetVehicleProperties(LastVehicles[#LastVehicles])
local model = CurrentVehicleData.model
if closestPlayer ~= -1 and closestDistance < 3 then
local newPlate = GeneratePlate()
local vehicleProps = ESX.Game.GetVehicleProperties(currentDisplayVehicle)
vehicleProps.plate = newPlate
SetVehicleNumberPlateText(LastVehicles[#LastVehicles], newPlate)
TriggerServerEvent('esx_vehicleshop:sellVehicle', model)
TriggerServerEvent('esx_vehicleshop:addToList', GetPlayerServerId(closestPlayer), model, newPlate)
if Config.EnableSocietyOwnedVehicles then
TriggerServerEvent('esx_vehicleshop:setVehicleOwnedSociety', xPlayer.job.name, vehicleProps)
ESX.ShowNotification(_U('vehicle_set_owned', vehicleProps.plate, GetPlayerName(closestPlayer)))
else
ESX.ShowNotification(_U('vehicle_sold_to', vehicleProps.plate, GetPlayerName(closestPlayer)))
end
end, GetPlayerServerId(closestPlayer))
end
elseif action == 'set_vehicle_owner_rent' then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'set_vehicle_owner_rent_amount', {
title = _U('rental_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('invalid_amount'))
SetVehicleNumberPlateText(currentDisplayVehicle, newPlate)
TriggerServerEvent('esx_vehicleshop:setVehicleOwnedPlayerId', GetPlayerServerId(closestPlayer), vehicleProps, CurrentVehicleData.model, CurrentVehicleData.name)
currentDisplayVehicle = nil
else
menu2.close()
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 5.0 then
ESX.ShowNotification(_U('no_players'))
else
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))
if Config.EnableOwnedVehicles then
TriggerServerEvent('esx_vehicleshop:setVehicleOwnedPlayerId', GetPlayerServerId(closestPlayer), vehicleProps)
end
ESX.ShowNotification(_U('vehicle_set_rented', vehicleProps.plate, GetPlayerName(closestPlayer)))
end
ESX.ShowNotification(_U('no_players'))
end
end, function(data2, menu2)
menu2.close()
end)
else
ESX.ShowNotification(_U('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 = _U('rental_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if not amount then
ESX.ShowNotification(_U('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(_U('no_players'))
end
end
end, function(data2, menu2)
menu2.close()
end)
else
ESX.ShowNotification(_U('no_players'))
end
else
ESX.ShowNotification(_U('no_current_vehicle'))
end
end
end, function(data, menu)
menu.close()
@@ -550,10 +446,12 @@ function OpenPopVehicleMenu()
ESX.TriggerServerCallback('esx_vehicleshop:getCommercialVehicles', function(vehicles)
local elements = {}
for i=1, #vehicles, 1 do
for k,v in ipairs(vehicles) do
local vehicleLabel = getVehicleLabelFromModel(v.vehicle)
table.insert(elements, {
label = ('%s [MSRP <span style="color:green;">%s</span>]'):format(vehicles[i].name, _U('generic_shopitem', ESX.Math.GroupDigits(vehicles[i].price))),
value = vehicles[i].name
label = ('%s [MSRP <span style="color:green;">%s</span>]'):format(vehicleLabel, _U('generic_shopitem', ESX.Math.GroupDigits(v.price))),
value = v.vehicle
})
end
@@ -563,11 +461,10 @@ function OpenPopVehicleMenu()
elements = elements
}, function(data, menu)
local model = data.current.value
DeleteShopInsideVehicles()
DeleteDisplayVehicleInsideShop()
ESX.Game.SpawnVehicle(model, Config.Zones.ShopInside.Pos, Config.Zones.ShopInside.Heading, function(vehicle)
table.insert(LastVehicles, vehicle)
currentDisplayVehicle = vehicle
for i=1, #Vehicles, 1 do
if model == Vehicles[i].model then
@@ -586,10 +483,12 @@ function OpenRentedVehiclesMenu()
ESX.TriggerServerCallback('esx_vehicleshop:getRentedVehicles', function(vehicles)
local elements = {}
for i=1, #vehicles, 1 do
for k,v in ipairs(vehicles) do
local vehicleLabel = getVehicleLabelFromModel(v.name)
table.insert(elements, {
label = ('%s: %s - <span style="color:orange;">%s</span>'):format(vehicles[i].playerName, vehicles[i].name, vehicles[i].plate),
value = vehicles[i].name
label = ('%s: %s - <span style="color:orange;">%s</span>'):format(v.playerName, vehicleLabel, v.plate),
value = v.name
})
end
@@ -660,10 +559,12 @@ function OpenGetStocksMenu()
local elements = {}
for i=1, #items, 1 do
table.insert(elements, {
label = 'x' .. items[i].count .. ' ' .. items[i].label,
value = items[i].name
})
if items[i].count > 0 then
table.insert(elements, {
label = 'x' .. items[i].count .. ' ' .. items[i].label,
value = items[i].name
})
end
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'stocks_menu', {
@@ -774,7 +675,6 @@ AddEventHandler('esx_vehicleshop:hasEnteredMarker', function(zone)
end
elseif zone == 'GiveBackVehicle' and Config.EnablePlayerManagement then
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
@@ -784,14 +684,11 @@ AddEventHandler('esx_vehicleshop:hasEnteredMarker', function(zone)
CurrentActionMsg = _U('vehicle_menu')
CurrentActionData = {vehicle = vehicle}
end
elseif zone == 'ResellVehicle' then
local playerPed = PlayerPedId()
if IsPedSittingInAnyVehicle(playerPed) then
local vehicle = GetVehiclePedIsIn(playerPed, false)
local vehicle = GetVehiclePedIsIn(playerPed, false)
local vehicleData, model, resellPrice, plate
if GetPedInVehicleSeat(vehicle, -1) == playerPed then
@@ -817,15 +714,12 @@ AddEventHandler('esx_vehicleshop:hasEnteredMarker', function(zone)
plate = plate
}
end
end
elseif zone == 'BossActions' and Config.EnablePlayerManagement and ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'cardealer' and ESX.PlayerData.job.grade_name == 'boss' then
CurrentAction = 'boss_actions_menu'
CurrentActionMsg = _U('shop_menu')
CurrentActionData = {}
end
end)
@@ -842,13 +736,14 @@ AddEventHandler('onResourceStop', function(resource)
if IsInShopMenu then
ESX.UI.Menu.CloseAll()
DeleteShopInsideVehicles()
local playerPed = PlayerPedId()
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
SetEntityCoords(playerPed, Config.Zones.ShopEntering.Pos)
end
DeleteDisplayVehicleInsideShop()
end
end)
@@ -874,8 +769,8 @@ Citizen.CreateThread(function()
SetBlipScale (blip, 1.0)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(_U('car_dealer'))
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName(_U('car_dealer'))
EndTextCommandSetBlipName(blip)
end)
@@ -979,4 +874,4 @@ Citizen.CreateThread(function()
LoadInterior(interiorID)
EnableInteriorProp(interiorID, 'csr_beforeMission') -- Load large window
RefreshInterior(interiorID)
end)
end)
+2 -2
View File
@@ -19,7 +19,7 @@ function GeneratePlate()
generatedPlate = string.upper(GetRandomLetter(Config.PlateLetters) .. GetRandomNumber(Config.PlateNumbers))
end
ESX.TriggerServerCallback('esx_vehicleshop:isPlateTaken', function (isPlateTaken)
ESX.TriggerServerCallback('esx_vehicleshop:isPlateTaken', function(isPlateTaken)
if not isPlateTaken then
doBreak = true
end
@@ -66,4 +66,4 @@ function GetRandomLetter(length)
else
return ''
end
end
end
+2 -4
View File
@@ -1,9 +1,7 @@
Config = {}
Config.DrawDistance = 100.0
Config.MarkerColor = { r = 120, g = 120, b = 240 }
Config.DrawDistance = 100
Config.MarkerColor = {r = 120, g = 120, b = 240}
Config.EnablePlayerManagement = false -- enables the actual car dealer job. You'll need esx_addonaccount, esx_billing and esx_society
Config.EnableOwnedVehicles = true
Config.EnableSocietyOwnedVehicles = false -- use with EnablePlayerManagement disabled, or else it wont have any effects
Config.ResellPercentage = 50
Config.Locale = 'fr'
+1 -4
View File
@@ -5,9 +5,6 @@ Locales['br'] = {
['vehicle_belongs'] = 'um veículo com placa ~y~%s~s~ agora pertence a ~b~you~s~',
['broke_company'] = 'você não tem dinheiro suficiente na conta da empresa',
['license_missing'] = 'você não tem carteira de motorista!',
['purchase_type'] = 'tipo de compra',
['society_type'] = 'sociedade',
['staff_type'] = 'uso pessoal',
['buy_vehicle_shop'] = 'comprar %s por $%s?',
['buy_vehicle'] = 'comprar veículo',
['car_dealer'] = 'Concessionária de carros',
@@ -18,6 +15,7 @@ Locales['br'] = {
['depop_vehicle'] = 'volte ao veiculo',
['return_provider'] = 'devolver veículo ao fornecedor',
['get_rented_vehicles'] = 'veículos para alugar',
['no_current_vehicle'] = 'you do not currently have an vehicle displayed',
['invalid_amount'] = 'Montante inválido',
['invoice_amount'] = 'valor da fatura',
['no'] = 'não',
@@ -34,7 +32,6 @@ Locales['br'] = {
['sell_menu'] = 'Pressione ~INPUT_CONTEXT~ para vender ',
['set_vehicle_owner_rent'] = 'Atribuir veículo [Alugar]',
['set_vehicle_owner_sell'] = 'Veículos para [Venda]',
['set_vehicle_owner_sell_society'] = 'atribuir veículo [Sale] [Society]',
['shop_menu'] = 'pressione ~INPUT_CONTEXT~ para acessar o menu',
['generic_shopitem'] = '$%s',
['vehicle_dealer'] = 'Veículo - Concessionária',
+5 -8
View File
@@ -5,9 +5,6 @@ Locales['en'] = {
['vehicle_belongs'] = 'an vehicle with plate ~y~%s~s~ now belongs to ~b~you~s~',
['broke_company'] = 'you do not have enough money in the company account',
['license_missing'] = 'you don\'t have a driver\'s license!',
['purchase_type'] = 'type of purchase',
['society_type'] = 'society',
['staff_type'] = 'personal usage',
['buy_vehicle_shop'] = 'do you want to purchase %s for $%s?',
['buy_vehicle'] = 'buy vehicle',
['car_dealer'] = 'car Dealership',
@@ -15,14 +12,15 @@ Locales['en'] = {
['create_bill'] = 'create bill',
['dealer_boss'] = 'car Dealer - Boss',
['delivered'] = 'the vehicle has been ~g~delivered~s~ to the dealer',
['depop_vehicle'] = 'return vehicle',
['depop_vehicle'] = 'return vehicle to garage',
['return_provider'] = 'return vehicle to provider',
['get_rented_vehicles'] = 'vehicles for rent',
['no_current_vehicle'] = 'you do not currently have an vehicle displayed',
['invalid_amount'] = 'invalid amount',
['invoice_amount'] = 'invoice amount',
['no'] = 'no',
['yes'] = 'yes',
['no_players'] = 'no players nearby',
['no_players'] = 'there is no players near you',
['not_enough_money'] = 'you do not have enough money',
['not_rental'] = 'this is not a ~r~rental vehicle~s~',
['not_yours'] = 'this vehicle does not belong to you',
@@ -32,14 +30,13 @@ Locales['en'] = {
['return_provider_menu'] = 'car Dealer - Return vehicle to provider',
['rental_amount'] = 'rental amount',
['sell_menu'] = 'press ~INPUT_CONTEXT~ to sell your ~y~%s~s~ for ~g~$%s~s~',
['set_vehicle_owner_rent'] = 'assign vehicle [Location]',
['set_vehicle_owner_rent'] = 'rent vehicle',
['set_vehicle_owner_sell'] = 'sell vehicle',
['set_vehicle_owner_sell_society'] = 'assign Vehicle [Sale] [Society]',
['shop_menu'] = 'press ~INPUT_CONTEXT~ to access the menu',
['generic_shopitem'] = '$%s',
['vehicle_dealer'] = 'vehicle - Car Dealer',
['vehicle_menu'] = 'press ~INPUT_CONTEXT~ to give back the rented vehicle',
['vehicle_purchased'] = 'you bought a vehicle',
['vehicle_purchased'] = 'you bought an 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_sold_for'] = 'the ~b~%s~s~ has been ~y~sold~s~ for ~g~$%s~s~',
+1 -4
View File
@@ -5,9 +5,6 @@ Locales['fi'] = {
['vehicle_belongs'] = 'ajoneuvo kilvellä ~y~%s~s~ on nyt ~b~sinun~s~ omistuksessasi',
['broke_company'] = 'sinulla ei ole tarpeeksi rahaa yrityksen tilillä',
['license_missing'] = 'you don\'t have a driver\'s license!',
['purchase_type'] = 'osto tyyppi',
['society_type'] = 'firma',
['staff_type'] = 'henkilökunta',
['buy_vehicle_shop'] = 'haluatko ostaa ajoneuvon %s hintaan $%s?',
['buy_vehicle'] = 'osta ajoneuvo',
['car_dealer'] = 'autokauppa',
@@ -18,6 +15,7 @@ Locales['fi'] = {
['depop_vehicle'] = 'palauta ajoneuvo',
['return_provider'] = 'return vehicle to provider',
['get_rented_vehicles'] = 'vuokrattavat ajoneuvot',
['no_current_vehicle'] = 'you do not currently have an vehicle displayed',
['invalid_amount'] = 'virheellinen summa',
['invoice_amount'] = 'laskun summa',
['no'] = 'ei',
@@ -34,7 +32,6 @@ Locales['fi'] = {
['sell_menu'] = 'paina ~INPUT_CONTEXT~ myydäksesi ~y~%s~s~ hintaan: ~g~$%s~s~',
['set_vehicle_owner_rent'] = 'määritä ajoneuvon [Vuokra]',
['set_vehicle_owner_sell'] = 'myy ajoneuvo',
['set_vehicle_owner_sell_society'] = 'määritä ajoneuvon [Hinta] [Firma]',
['shop_menu'] = 'paina ~INPUT_CONTEXT~ avataksesi menu',
['generic_shopitem'] = '$%s',
['vehicle_dealer'] = 'ajonevuo - Autokauppa',
+1 -4
View File
@@ -5,9 +5,6 @@ Locales['fr'] = {
['vehicle_belongs'] = 'le véhicule avec la plaque ~y~%s~s~ est désormais à ~b~vous~s~',
['broke_company'] = 'vous n\avez pas assez d\'argent sur le compte de la societé',
['license_missing'] = 'you don\'t have a driver\'s license!',
['purchase_type'] = 'type d\'achat',
['society_type'] = 'societé',
['staff_type'] = 'personnel',
['buy_vehicle_shop'] = 'acheter %s pour $%s?',
['buy_vehicle'] = 'acheter véhicule',
['car_dealer'] = 'concessionnaire',
@@ -18,6 +15,7 @@ Locales['fr'] = {
['depop_vehicle'] = 'rentrer véhicule',
['return_provider'] = 'rendre le véhicule',
['get_rented_vehicles'] = 'véhicules en location',
['no_current_vehicle'] = 'you do not currently have an vehicle displayed',
['invalid_amount'] = 'montant invalide',
['invoice_amount'] = 'montant de la facture',
['no'] = 'non',
@@ -34,7 +32,6 @@ Locales['fr'] = {
['sell_menu'] = 'appuyez sur ~INPUT_CONTEXT~ pour vendre ~y~%s~s~ au prix de ~g~$%s~s~',
['set_vehicle_owner_rent'] = 'attribuer véhicule [Location]',
['set_vehicle_owner_sell'] = 'attribuer véhicule [Vente]',
['set_vehicle_owner_sell_society'] = 'attribuer véhicule [Vente] [Société]',
['shop_menu'] = 'appuyez sur ~INPUT_CONTEXT~ pour accéder au menu',
['generic_shopitem'] = '$%s',
['vehicle_dealer'] = 'concessionnaire - Véhicules',
+1 -4
View File
@@ -5,9 +5,6 @@ Locales['pl'] = {
['vehicle_belongs'] = 'pojazd z rejestracją ~y~%s~s~ teraz należy do ~b~ciebie~s~',
['broke_company'] = 'twoja firma nie ma wystarczająco pieniedzy',
['license_missing'] = 'you don\'t have a driver\'s license!',
['purchase_type'] = 'rodzaj zakupu',
['society_type'] = 'firma',
['staff_type'] = 'pracownicy',
['buy_vehicle_shop'] = 'czy chcesz kupić %s za $%s?',
['buy_vehicle'] = 'kup pojazd',
['car_dealer'] = 'sprzedawca Aut',
@@ -18,6 +15,7 @@ Locales['pl'] = {
['depop_vehicle'] = 'oddaj pojazd',
['return_provider'] = 'return vehicle to provider',
['get_rented_vehicles'] = 'pojazdy do wynajęcia',
['no_current_vehicle'] = 'you do not currently have an vehicle displayed',
['invalid_amount'] = 'nieprawidłowa ilość',
['invoice_amount'] = 'suma faktury',
['no'] = 'nie',
@@ -34,7 +32,6 @@ Locales['pl'] = {
['sell_menu'] = 'wcisnij ~INPUT_CONTEXT~ aby sprzedać ~y~%s~s~ za ~g~$%s~s~',
['set_vehicle_owner_rent'] = 'zarejestruj pojazd [Wynajem]',
['set_vehicle_owner_sell'] = 'zarejestruj pojazd [Kupno]',
['set_vehicle_owner_sell_society'] = 'zarejestruj pojazd [Firmowe]',
['shop_menu'] = 'wcisnij ~INPUT_CONTEXT~ aby wejść do menu',
['generic_shopitem'] = '$%s',
['vehicle_dealer'] = 'pojazdy - Sprzedawca aut',
+2 -5
View File
@@ -1,13 +1,10 @@
Locales['sv'] = {
-- global menus
['not_enough_in_society'] = 'det finns inte tillräckligt många ~r~ det föremålet~s~ i förrådet!',
['not_enough_in_society'] = 'det finns inte tillräckligt många av ~r~det föremålet~s~ i förrådet!',
['player_cannot_hold'] = 'du har ~r~inte~s~ tillräckligt mycket~y~plats~s~ på dig!',
['vehicle_belongs'] = 'fordonet med reg numret ~y~%s~s~ tillhör nu ~b~dig~s~',
['broke_company'] = 'det finns inte tillräckligt mycket pengar i företagskontot',
['license_missing'] = 'du är inte behörig att köpa bilar, B-körkort krävs!',
['purchase_type'] = 'till vem är fordonet?',
['society_type'] = 'företag',
['staff_type'] = 'personlig användning',
['buy_vehicle_shop'] = 'vill du köpa in %s för %s SEK?',
['buy_vehicle'] = 'Köp in fordon',
['car_dealer'] = 'bilförsäljare',
@@ -18,6 +15,7 @@ Locales['sv'] = {
['depop_vehicle'] = 'ställ tillbaka fordonet',
['return_provider'] = 'sälj tillbaka fordon till leverantör',
['get_rented_vehicles'] = 'uthyrda fordon',
['no_current_vehicle'] = 'du har inget fordon ute till salu',
['invalid_amount'] = 'ogiltigt belopp',
['invoice_amount'] = 'belopp att betala',
['no'] = 'nej',
@@ -34,7 +32,6 @@ Locales['sv'] = {
['sell_menu'] = 'tryck ~INPUT_CONTEXT~ för att sälja ~y~%s~s~ för ~g~%s SEK~s~',
['set_vehicle_owner_rent'] = 'hyr ut fordon',
['set_vehicle_owner_sell'] = 'sälj fordon',
['set_vehicle_owner_sell_society'] = 'sälj fordon till företag',
['shop_menu'] = 'tryck ~INPUT_CONTEXT~ för öppna ~y~bilförsäljarsmenyn~s~.',
['generic_shopitem'] = '%s SEK',
['vehicle_dealer'] = 'bilförsäljare - fordon för visning',
+187 -222
View File
@@ -1,5 +1,5 @@
ESX = nil
local Categories, Vehicles = {}, {}
local categories, vehicles = {}, {}
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
@@ -12,7 +12,7 @@ Citizen.CreateThread(function()
if Config.PlateUseSpace then char = char + 1 end
if char > 8 then
print(('esx_vehicleshop: ^1WARNING^7 plate character count reached, %s/8 characters.'):format(char))
print(('[esx_vehicleshop] [^3WARNING^7] Plate character count reached, %s/8 characters!'):format(char))
end
end)
@@ -23,132 +23,117 @@ function RemoveOwnedVehicle(plate)
end
MySQL.ready(function()
Categories = MySQL.Sync.fetchAll('SELECT * FROM vehicle_categories')
local vehicles = MySQL.Sync.fetchAll('SELECT * FROM vehicles')
MySQL.Async.fetchAll('SELECT * FROM vehicle_categories', {}, function(_categories)
categories = _categories
for i=1, #vehicles, 1 do
local vehicle = vehicles[i]
MySQL.Async.fetchAll('SELECT * FROM vehicles', {}, function(_vehicles)
vehicles = _vehicles
for j=1, #Categories, 1 do
if Categories[j].name == vehicle.category then
vehicle.categoryLabel = Categories[j].label
break
for k,v in ipairs(vehicles) do
for k2,v2 in ipairs(categories) do
if v2.name == v.category then
vehicles[k].categoryLabel = v2.label
break
end
end
end
end
table.insert(Vehicles, vehicle)
-- send information after db has loaded, making sure everyone gets vehicle information
TriggerClientEvent('esx_vehicleshop:sendCategories', -1, categories)
TriggerClientEvent('esx_vehicleshop:sendVehicles', -1, vehicles)
end)
end)
end)
function getVehicleLabelFromModel(model)
for k,v in ipairs(vehicles) do
if v.model == model then
return v.name
end
end
-- send information after db has loaded, making sure everyone gets vehicle information
TriggerClientEvent('esx_vehicleshop:sendCategories', -1, Categories)
TriggerClientEvent('esx_vehicleshop:sendVehicles', -1, Vehicles)
end)
return
end
RegisterServerEvent('esx_vehicleshop:setVehicleOwned')
AddEventHandler('esx_vehicleshop:setVehicleOwned', function(vehicleProps)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
RegisterNetEvent('esx_vehicleshop:setVehicleOwnedPlayerId')
AddEventHandler('esx_vehicleshop:setVehicleOwnedPlayerId', function(playerId, vehicleProps, model, label)
local xPlayer, xTarget = ESX.GetPlayerFromId(source), ESX.GetPlayerFromId(playerId)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle) VALUES (@owner, @plate, @vehicle)',
{
['@owner'] = xPlayer.identifier,
['@plate'] = vehicleProps.plate,
['@vehicle'] = json.encode(vehicleProps)
}, function(rowsChanged)
xPlayer.showNotification(_U('vehicle_belongs', vehicleProps.plate))
end)
end)
if xPlayer.job.name == 'cardealer' and xTarget then
MySQL.Async.fetchAll('SELECT id FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = model
}, function(result)
if result[1] then
local id = result[1].id
RegisterServerEvent('esx_vehicleshop:setVehicleOwnedPlayerId')
AddEventHandler('esx_vehicleshop:setVehicleOwnedPlayerId', function(playerId, vehicleProps)
local xPlayer = ESX.GetPlayerFromId(playerId)
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = id
}, function(rowsChanged)
if rowsChanged == 1 then
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle) VALUES (@owner, @plate, @vehicle)', {
['@owner'] = xTarget.identifier,
['@plate'] = vehicleProps.plate,
['@vehicle'] = json.encode(vehicleProps)
}, function(rowsChanged)
xPlayer.showNotification(_U('vehicle_set_owned', vehicleProps.plate, xTarget.getName()))
xTarget.showNotification(_U('vehicle_belongs', vehicleProps.plate))
end)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle) VALUES (@owner, @plate, @vehicle)',
{
['@owner'] = xPlayer.identifier,
['@plate'] = vehicleProps.plate,
['@vehicle'] = json.encode(vehicleProps)
}, function(rowsChanged)
xPlayer.showNotification(_U('vehicle_belongs', vehicleProps.plate))
end)
end)
local dateNow = os.date('%Y-%m-%d %H:%M')
RegisterServerEvent('esx_vehicleshop:setVehicleOwnedSociety')
AddEventHandler('esx_vehicleshop:setVehicleOwnedSociety', function(society, vehicleProps)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle) VALUES (@owner, @plate, @vehicle)', {
['@owner'] = 'society:' .. society,
['@plate'] = vehicleProps.plate,
['@vehicle'] = json.encode(vehicleProps),
}, function(rowsChanged) end)
end)
RegisterServerEvent('esx_vehicleshop:sellVehicle')
AddEventHandler('esx_vehicleshop:sellVehicle', function(vehicle)
MySQL.Async.fetchAll('SELECT * FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = vehicle
}, function(result)
local id = result[1].id
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = id
})
end)
end)
RegisterServerEvent('esx_vehicleshop:addToList')
AddEventHandler('esx_vehicleshop:addToList', function(target, model, plate)
local xPlayer, xTarget = ESX.GetPlayerFromId(source), ESX.GetPlayerFromId(target)
local dateNow = os.date('%Y-%m-%d %H:%M')
if xPlayer.job.name == 'cardealer' then
MySQL.Async.execute('INSERT INTO vehicle_sold (client, model, plate, soldby, date) VALUES (@client, @model, @plate, @soldby, @date)', {
['@client'] = xTarget.getName(),
['@model'] = model,
['@plate'] = plate,
['@soldby'] = xPlayer.getName(),
['@date'] = dateNow
})
else
print(('esx_vehicleshop: %s attempted to add a sold vehicle to list!'):format(xPlayer.identifier))
MySQL.Async.execute('INSERT INTO vehicle_sold (client, model, plate, soldby, date) VALUES (@client, @model, @plate, @soldby, @date)', {
['@client'] = xTarget.getName(),
['@model'] = label,
['@plate'] = vehicleProps.plate,
['@soldby'] = xPlayer.getName(),
['@date'] = dateNow
})
end
end)
end
end)
end
end)
ESX.RegisterServerCallback('esx_vehicleshop:getSoldVehicles', function(source, cb)
MySQL.Async.fetchAll('SELECT * FROM vehicle_sold', {}, function(result)
MySQL.Async.fetchAll('SELECT client, model, plate, soldby, date FROM vehicle_sold', {}, function(result)
cb(result)
end)
end)
RegisterServerEvent('esx_vehicleshop:rentVehicle')
AddEventHandler('esx_vehicleshop:rentVehicle', function(vehicle, plate, playerName, basePrice, rentPrice, target)
local xPlayer = ESX.GetPlayerFromId(target)
RegisterNetEvent('esx_vehicleshop:rentVehicle')
AddEventHandler('esx_vehicleshop:rentVehicle', function(vehicle, plate, rentPrice, playerId)
local xPlayer, xTarget = ESX.GetPlayerFromId(source), ESX.GetPlayerFromId(playerId)
MySQL.Async.fetchAll('SELECT * FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = vehicle
}, function(result)
local id = result[1].id
local price = result[1].price
local owner = xPlayer.identifier
if xPlayer.job.name == 'cardealer' and xTarget then
MySQL.Async.fetchAll('SELECT id, price FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = vehicle
}, function(result)
if result[1] then
local price = result[1].price
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = id
})
MySQL.Async.execute('INSERT INTO rented_vehicles (vehicle, plate, player_name, base_price, rent_price, owner) VALUES (@vehicle, @plate, @player_name, @base_price, @rent_price, @owner)', {
['@vehicle'] = vehicle,
['@plate'] = plate,
['@player_name'] = playerName,
['@base_price'] = basePrice,
['@rent_price'] = rentPrice,
['@owner'] = owner
})
end)
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = result[1].id
}, function(rowsChanged)
if rowsChanged == 1 then
MySQL.Async.execute('INSERT INTO rented_vehicles (vehicle, plate, player_name, base_price, rent_price, owner) VALUES (@vehicle, @plate, @player_name, @base_price, @rent_price, @owner)', {
['@vehicle'] = vehicle,
['@plate'] = plate,
['@player_name'] = xTarget.getName(),
['@base_price'] = price,
['@rent_price'] = rentPrice,
['@owner'] = xTarget.identifier
}, function(rowsChanged2)
xPlayer.showNotification(_U('vehicle_set_rented', plate, xTarget.getName()))
end)
end
end)
end
end)
end
end)
RegisterServerEvent('esx_vehicleshop:getStockItem')
RegisterNetEvent('esx_vehicleshop:getStockItem')
AddEventHandler('esx_vehicleshop:getStockItem', function(itemName, count)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
@@ -173,7 +158,7 @@ AddEventHandler('esx_vehicleshop:getStockItem', function(itemName, count)
end)
end)
RegisterServerEvent('esx_vehicleshop:putStockItems')
RegisterNetEvent('esx_vehicleshop:putStockItems')
AddEventHandler('esx_vehicleshop:putStockItems', function(itemName, count)
local _source = source
local xPlayer = ESX.GetPlayerFromId(_source)
@@ -192,98 +177,107 @@ AddEventHandler('esx_vehicleshop:putStockItems', function(itemName, count)
end)
ESX.RegisterServerCallback('esx_vehicleshop:getCategories', function(source, cb)
cb(Categories)
cb(categories)
end)
ESX.RegisterServerCallback('esx_vehicleshop:getVehicles', function(source, cb)
cb(Vehicles)
cb(vehicles)
end)
ESX.RegisterServerCallback('esx_vehicleshop:buyVehicle', function(source, cb, vehicleModel)
ESX.RegisterServerCallback('esx_vehicleshop:buyVehicle', function(source, cb, model, plate)
local xPlayer = ESX.GetPlayerFromId(source)
local vehicleData
local modelPrice
for i=1, #Vehicles, 1 do
if Vehicles[i].model == vehicleModel then
vehicleData = Vehicles[i]
for k,v in ipairs(vehicles) do
if model == v.model then
modelPrice = v.price
break
end
end
if vehicleData and xPlayer.getMoney() >= vehicleData.price then
xPlayer.removeMoney(vehicleData.price)
cb(true)
if modelPrice and xPlayer.getMoney() >= modelPrice then
xPlayer.removeMoney(modelPrice)
MySQL.Async.execute('INSERT INTO owned_vehicles (owner, plate, vehicle) VALUES (@owner, @plate, @vehicle)', {
['@owner'] = xPlayer.identifier,
['@plate'] = plate,
['@vehicle'] = json.encode({model = GetHashKey(model)})
}, function(rowsChanged)
xPlayer.showNotification(_U('vehicle_belongs', plate))
cb(true)
end)
else
cb(false)
end
end)
ESX.RegisterServerCallback('esx_vehicleshop:buyVehicleSociety', function(source, cb, society, vehicleModel)
local vehicleData
ESX.RegisterServerCallback('esx_vehicleshop:getCommercialVehicles', function(source, cb)
MySQL.Async.fetchAll('SELECT price, vehicle FROM cardealer_vehicles ORDER BY vehicle ASC', {}, function(result)
cb(result)
end)
end)
for i=1, #Vehicles, 1 do
if Vehicles[i].model == vehicleModel then
vehicleData = Vehicles[i]
break
ESX.RegisterServerCallback('esx_vehicleshop:buyCarDealerVehicle', function(source, cb, model)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == 'cardealer' then
local modelPrice
for k,v in ipairs(vehicles) do
if model == v.model then
modelPrice = v.price
break
end
end
if modelPrice then
TriggerEvent('esx_addonaccount:getSharedAccount', 'society_cardealer', function(account)
if account.money >= modelPrice then
account.removeMoney(modelPrice)
MySQL.Async.execute('INSERT INTO cardealer_vehicles (vehicle, price) VALUES (@vehicle, @price)', {
['@vehicle'] = model,
['@price'] = modelPrice
}, function(rowsChanged)
cb(true)
end)
else
cb(false)
end
end)
end
end
TriggerEvent('esx_addonaccount:getSharedAccount', 'society_' .. society, function(account)
if account.money >= vehicleData.price then
account.removeMoney(vehicleData.price)
MySQL.Async.execute('INSERT INTO cardealer_vehicles (vehicle, price) VALUES (@vehicle, @price)', {
['@vehicle'] = vehicleData.model,
['@price'] = vehicleData.price
}, function(rowsChanged)
cb(true)
end)
else
cb(false)
end
end)
end)
ESX.RegisterServerCallback('esx_vehicleshop:getCommercialVehicles', function(source, cb)
MySQL.Async.fetchAll('SELECT * FROM cardealer_vehicles ORDER BY vehicle ASC', {}, function(result)
local vehicles = {}
for i=1, #result, 1 do
table.insert(vehicles, {
name = result[i].vehicle,
price = result[i].price
})
end
cb(vehicles)
end)
end)
RegisterServerEvent('esx_vehicleshop:returnProvider')
RegisterNetEvent('esx_vehicleshop:returnProvider')
AddEventHandler('esx_vehicleshop:returnProvider', function(vehicleModel)
local _source = source
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT * FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = vehicleModel
}, function(result)
if result[1] then
local id = result[1].id
local price = ESX.Math.Round(result[1].price * 0.75)
if xPlayer.job.name == 'cardealer' then
MySQL.Async.fetchAll('SELECT id, price FROM cardealer_vehicles WHERE vehicle = @vehicle LIMIT 1', {
['@vehicle'] = vehicleModel
}, function(result)
if result[1] then
local id = result[1].id
TriggerEvent('esx_addonaccount:getSharedAccount', 'society_cardealer', function(account)
account.addMoney(price)
end)
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = id
}, function(rowsChanged)
if rowsChanged == 1 then
TriggerEvent('esx_addonaccount:getSharedAccount', 'society_cardealer', function(account)
local price = ESX.Math.Round(result[1].price * 0.75)
local vehicleLabel = getVehicleLabelFromModel(vehicleModel)
MySQL.Async.execute('DELETE FROM cardealer_vehicles WHERE id = @id', {
['@id'] = id
})
xPlayer.showNotification(_U('vehicle_sold_for', vehicleModel, ESX.Math.GroupDigits(price)))
else
print(('esx_vehicleshop: %s attempted selling an invalid vehicle!'):format(GetPlayerIdentifiers(_source)[1]))
end
end)
account.addMoney(price)
xPlayer.showNotification(_U('vehicle_sold_for', vehicleLabel, ESX.Math.GroupDigits(price)))
end)
end
end)
else
print(('[esx_vehicleshop] [^3WARNING^7] %s attempted selling an invalid vehicle!'):format(xPlayer.identifier))
end
end)
end
end)
ESX.RegisterServerCallback('esx_vehicleshop:getRentedVehicles', function(source, cb)
@@ -303,24 +297,24 @@ ESX.RegisterServerCallback('esx_vehicleshop:getRentedVehicles', function(source,
end)
ESX.RegisterServerCallback('esx_vehicleshop:giveBackVehicle', function(source, cb, plate)
MySQL.Async.fetchAll('SELECT * FROM rented_vehicles WHERE plate = @plate', {
MySQL.Async.fetchAll('SELECT base_price, vehicle FROM rented_vehicles WHERE plate = @plate', {
['@plate'] = plate
}, function(result)
if result[1] then
local vehicle = result[1].vehicle
local basePrice = result[1].base_price
MySQL.Async.execute('INSERT INTO cardealer_vehicles (vehicle, price) VALUES (@vehicle, @price)', {
['@vehicle'] = vehicle,
['@price'] = basePrice
})
MySQL.Async.execute('DELETE FROM rented_vehicles WHERE plate = @plate', {
['@plate'] = plate
})
RemoveOwnedVehicle(plate)
cb(true)
}, function(rowsChanged)
MySQL.Async.execute('INSERT INTO cardealer_vehicles (vehicle, price) VALUES (@vehicle, @price)', {
['@vehicle'] = vehicle,
['@price'] = basePrice
})
RemoveOwnedVehicle(plate)
cb(true)
end)
else
cb(false)
end
@@ -328,18 +322,18 @@ ESX.RegisterServerCallback('esx_vehicleshop:giveBackVehicle', function(source, c
end)
ESX.RegisterServerCallback('esx_vehicleshop:resellVehicle', function(source, cb, plate, model)
local resellPrice = 0
local resellPrice
-- calculate the resell price
for i=1, #Vehicles, 1 do
if GetHashKey(Vehicles[i].model) == model then
resellPrice = ESX.Math.Round(Vehicles[i].price / 100 * Config.ResellPercentage)
for i=1, #vehicles, 1 do
if GetHashKey(vehicles[i].model) == model then
resellPrice = ESX.Math.Round(vehicles[i].price / 100 * Config.ResellPercentage)
break
end
end
if resellPrice == 0 then
print(('esx_vehicleshop: %s attempted to sell an unknown vehicle!'):format(GetPlayerIdentifiers(source)[1]))
if not resellPrice then
print(('[esx_vehicleshop] [^3WARNING^7] %s attempted to sell an unknown vehicle!'):format(GetPlayerIdentifiers(source)[1]))
cb(false)
else
MySQL.Async.fetchAll('SELECT * FROM rented_vehicles WHERE plate = @plate', {
@@ -363,40 +357,11 @@ ESX.RegisterServerCallback('esx_vehicleshop:resellVehicle', function(source, cb,
RemoveOwnedVehicle(plate)
cb(true)
else
print(('esx_vehicleshop: %s attempted to sell an vehicle with plate mismatch!'):format(xPlayer.identifier))
print(('[esx_vehicleshop] [^3WARNING^7] %s attempted to sell an vehicle with plate mismatch!'):format(xPlayer.identifier))
cb(false)
end
else
print(('esx_vehicleshop: %s attempted to sell an vehicle with model mismatch!'):format(xPlayer.identifier))
cb(false)
end
else
if xPlayer.job.grade_name == 'boss' then
MySQL.Async.fetchAll('SELECT * FROM owned_vehicles WHERE owner = @owner AND @plate = plate', {
['@owner'] = 'society:' .. xPlayer.job.name,
['@plate'] = plate
}, function(result)
if result[1] then
local vehicle = json.decode(result[1].vehicle)
if vehicle.model == model then
if vehicle.plate == plate then
xPlayer.addMoney(resellPrice)
RemoveOwnedVehicle(plate)
cb(true)
else
print(('esx_vehicleshop: %s attempted to sell an vehicle with plate mismatch!'):format(xPlayer.identifier))
cb(false)
end
else
print(('esx_vehicleshop: %s attempted to sell an vehicle with model mismatch!'):format(xPlayer.identifier))
cb(false)
end
else
cb(false)
end
end)
else
print(('[esx_vehicleshop] [^3WARNING^7] %s attempted to sell an vehicle with model mismatch!'):format(xPlayer.identifier))
cb(false)
end
end
@@ -439,7 +404,7 @@ ESX.RegisterServerCallback('esx_vehicleshop:retrieveJobVehicles', function(sourc
end)
end)
RegisterServerEvent('esx_vehicleshop:setJobVehicleState')
RegisterNetEvent('esx_vehicleshop:setJobVehicleState')
AddEventHandler('esx_vehicleshop:setJobVehicleState', function(plate, state)
local xPlayer = ESX.GetPlayerFromId(source)
@@ -449,7 +414,7 @@ AddEventHandler('esx_vehicleshop:setJobVehicleState', function(plate, state)
['@job'] = xPlayer.job.name
}, function(rowsChanged)
if rowsChanged == 0 then
print(('esx_vehicleshop: %s exploited the garage!'):format(xPlayer.identifier))
print(('[esx_vehicleshop] [^3WARNING^7] %s exploited the garage!'):format(xPlayer.identifier))
end
end)
end)