Advertisement
OfficialMonkey

vehicleshop/client.lua

Mar 15th, 2022
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.43 KB | None | 0 0
  1. -- Variables
  2. local QBCore = exports['qb-core']:GetCoreObject()
  3. local PlayerData = QBCore.Functions.GetPlayerData() -- Just for resource restart (same as event handler)
  4. local insideZones = {}
  5.  
  6. for name, shop in pairs(Config.Shops) do -- foreach shop
  7. insideZones[name] = false -- default to not being in a shop
  8. end
  9.  
  10. local testDriveVeh, inTestDrive = 0, false
  11. local ClosestVehicle = 1
  12. local zones = {}
  13.  
  14. function getShopInsideOf()
  15. for name, shop in pairs(Config.Shops) do -- foreach shop
  16. if insideZones[name] then
  17. return name
  18. end
  19. end
  20. return nil
  21. end
  22.  
  23. -- Handlers
  24.  
  25. AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
  26. PlayerData = QBCore.Functions.GetPlayerData()
  27. local citizenid = PlayerData.citizenid
  28. local gameTime = GetGameTimer()
  29. TriggerServerEvent('qb-vehicleshop:server:addPlayer', citizenid, gameTime)
  30. TriggerServerEvent('qb-vehicleshop:server:checkFinance')
  31. end)
  32.  
  33. RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
  34. PlayerData.job = JobInfo
  35. end)
  36.  
  37. RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
  38. local citizenid = PlayerData.citizenid
  39. TriggerServerEvent('qb-vehicleshop:server:removePlayer', citizenid)
  40. PlayerData = {}
  41. end)
  42.  
  43. -- Static Headers
  44.  
  45. local vehHeaderMenu = {
  46. {
  47. header = 'Vehicle Options',
  48. txt = 'Interact with the current vehicle',
  49. params = {
  50. event = 'qb-vehicleshop:client:showVehOptions'
  51. }
  52. }
  53. }
  54.  
  55. local financeMenu = {
  56. {
  57. header = 'Financed Vehicles',
  58. txt = 'Browse your owned vehicles',
  59. params = {
  60. event = 'qb-vehicleshop:client:getVehicles'
  61. }
  62. }
  63. }
  64.  
  65. local returnTestDrive = {
  66. {
  67. header = 'Finish Test Drive',
  68. params = {
  69. event = 'qb-vehicleshop:client:TestDriveReturn'
  70. }
  71. }
  72. }
  73.  
  74. -- Functions
  75.  
  76. local function drawTxt(text,font,x,y,scale,r,g,b,a)
  77. SetTextFont(font)
  78. SetTextScale(scale,scale)
  79. SetTextColour(r,g,b,a)
  80. SetTextOutline()
  81. SetTextCentre(1)
  82. SetTextEntry("STRING")
  83. AddTextComponentString(text)
  84. DrawText(x,y)
  85. end
  86.  
  87. local function comma_value(amount)
  88. local formatted = amount
  89. while true do
  90. formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
  91. if (k==0) then
  92. break
  93. end
  94. end
  95. return formatted
  96. end
  97.  
  98. local function getVehName()
  99. return QBCore.Shared.Vehicles[Config.Shops[getShopInsideOf()]["ShowroomVehicles"][ClosestVehicle].chosenVehicle]["name"]
  100. end
  101.  
  102. local function getVehBrand()
  103. return QBCore.Shared.Vehicles[Config.Shops[getShopInsideOf()]["ShowroomVehicles"][ClosestVehicle].chosenVehicle]["brand"]
  104. end
  105.  
  106. local function setClosestShowroomVehicle()
  107. local pos = GetEntityCoords(PlayerPedId(), true)
  108. local current = nil
  109. local dist = nil
  110. local closestShop = getShopInsideOf()
  111. for id, veh in pairs(Config.Shops[closestShop]["ShowroomVehicles"]) do
  112. local dist2 = #(pos - vector3(Config.Shops[closestShop]["ShowroomVehicles"][id].coords.x, Config.Shops[closestShop]["ShowroomVehicles"][id].coords.y, Config.Shops[closestShop]["ShowroomVehicles"][id].coords.z))
  113. if current ~= nil then
  114. if dist2 < dist then
  115. current = id
  116. dist = dist2
  117. end
  118. else
  119. dist = dist2
  120. current = id
  121. end
  122. end
  123. if current ~= ClosestVehicle then
  124. ClosestVehicle = current
  125. end
  126. end
  127.  
  128. local function createTestDriveReturn()
  129. testDriveZone = BoxZone:Create(
  130. Config.Shops[getShopInsideOf()]["ReturnLocation"],
  131. 3.0,
  132. 5.0, {
  133. name="box_zone"
  134. })
  135.  
  136. testDriveZone:onPlayerInOut(function(isPointInside)
  137. if isPointInside and IsPedInAnyVehicle(PlayerPedId()) then
  138. SetVehicleForwardSpeed(GetVehiclePedIsIn(PlayerPedId(), false), 0)
  139. exports['qb-menu']:openMenu(returnTestDrive)
  140. else
  141. exports['qb-menu']:closeMenu()
  142. end
  143. end)
  144. end
  145.  
  146. local function startTestDriveTimer(testDriveTime)
  147. local gameTimer = GetGameTimer()
  148. CreateThread(function()
  149. while inTestDrive do
  150. Wait(1)
  151. if GetGameTimer() < gameTimer+tonumber(1000*testDriveTime) then
  152. local secondsLeft = GetGameTimer() - gameTimer
  153. drawTxt('Test Drive Time Remaining: '..math.ceil(testDriveTime - secondsLeft/1000),4,0.5,0.93,0.50,255,255,255,180)
  154. end
  155. end
  156. end)
  157. end
  158.  
  159. local function isInShop()
  160. for shopName, isInside in pairs(insideZones) do
  161. if isInside then
  162. return true
  163. end
  164. end
  165.  
  166. return false
  167. end
  168.  
  169. local function createVehZones(shopName) -- This will create an entity zone if config is true that you can use to target and open the vehicle menu
  170. if not Config.UsingTarget then
  171. for i = 1, #Config.Shops[shopName]['ShowroomVehicles'] do
  172. zones[#zones+1] = BoxZone:Create(
  173. vector3(Config.Shops[shopName]['ShowroomVehicles'][i]['coords'].x,
  174. Config.Shops[shopName]['ShowroomVehicles'][i]['coords'].y,
  175. Config.Shops[shopName]['ShowroomVehicles'][i]['coords'].z),
  176. 2.75,
  177. 2.75, {
  178. name="box_zone",
  179. debugPoly=false,
  180. })
  181. end
  182. local combo = ComboZone:Create(zones, {name = "vehCombo", debugPoly = false})
  183. combo:onPlayerInOut(function(isPointInside)
  184. local insideShop = getShopInsideOf()
  185. if isPointInside then
  186. if PlayerData.job.name == Config.Shops[insideShop]['Job'] or Config.Shops[insideShop]['Job'] == 'none' then
  187. exports['qb-menu']:showHeader(vehHeaderMenu)
  188. end
  189. else
  190. exports['qb-menu']:closeMenu()
  191. end
  192. end)
  193. else
  194. exports['qb-target']:AddGlobalVehicle({
  195. options = {
  196. {
  197. type = "client",
  198. event = "qb-vehicleshop:client:showVehOptions",
  199. icon = "fas fa-car",
  200. label = "Vehicle Interaction",
  201. canInteract = function(entity)
  202. local closestShop = getShopInsideOf()
  203. if (closestShop ~= nil) and (Config.Shops[closestShop]['Job'] == 'none' or PlayerData.job.name == Config.Shops[closestShop]['Job']) then
  204. return true
  205. end
  206. return false
  207. end
  208. },
  209. },
  210. distance = 2.0
  211. })
  212. end
  213. end
  214.  
  215. -- Zones
  216.  
  217. function createFreeUseShop(shopShape, name)
  218. local zone = PolyZone:Create(shopShape, { -- create the zone
  219. name= name,
  220. minZ = shopShape.minZ,
  221. maxZ = shopShape.maxZ
  222. })
  223.  
  224. zone:onPlayerInOut(function(isPointInside)
  225. if isPointInside then
  226. insideZones[name] = true
  227. CreateThread(function()
  228. while insideZones[name] do
  229. setClosestShowroomVehicle()
  230. vehicleMenu = {
  231. {
  232. isMenuHeader = true,
  233. header = getVehBrand():upper().. ' '..getVehName():upper().. ' - $' ..getVehPrice(),
  234. },
  235. {
  236. header = 'Test Drive',
  237. txt = 'Test drive currently selected vehicle',
  238. params = {
  239. event = 'qb-vehicleshop:client:TestDrive',
  240. }
  241. },
  242. {
  243. header = "Buy Vehicle",
  244. txt = 'Purchase currently selected vehicle',
  245. params = {
  246. isServer = true,
  247. event = 'qb-vehicleshop:server:buyShowroomVehicle',
  248. args = {
  249. buyVehicle = Config.Shops[getShopInsideOf()]["ShowroomVehicles"][ClosestVehicle].chosenVehicle
  250. }
  251. }
  252. },
  253. {
  254. header = 'Finance Vehicle',
  255. txt = 'Finance currently selected vehicle',
  256. params = {
  257. event = 'qb-vehicleshop:client:openFinance',
  258. args = {
  259. price = getVehPrice(),
  260. buyVehicle = Config.Shops[getShopInsideOf()]["ShowroomVehicles"][ClosestVehicle].chosenVehicle
  261. }
  262. }
  263. },
  264. {
  265. header = 'Swap Vehicle',
  266. txt = 'Change currently selected vehicle',
  267. params = {
  268. event = 'qb-vehicleshop:client:vehCategories',
  269. }
  270. },
  271. }
  272. Wait(1000)
  273. end
  274. end)
  275. else
  276. insideZones[name] = false -- leave the shops zone
  277. ClosestVehicle = 1
  278. end
  279. end)
  280. end
  281.  
  282. function createManagedShop(shopShape, name, jobName)
  283. local zone = PolyZone:Create(shopShape, { -- create the zone
  284. name= name,
  285. minZ = shopShape.minZ,
  286. maxZ = shopShape.maxZ
  287. })
  288.  
  289. zone:onPlayerInOut(function(isPointInside)
  290. if isPointInside then
  291. insideZones[name] = true
  292. CreateThread(function()
  293. while insideZones[name] and PlayerData.job ~= nil and PlayerData.job.name == Config.Shops[name]['Job'] do
  294. setClosestShowroomVehicle()
  295. local closestShop = getShopInsideOf()
  296. vehicleMenu = {
  297. {
  298. isMenuHeader = true,
  299. header = getVehBrand():upper().. ' '..getVehName():upper().. ' - $' ..getVehPrice(),
  300. },
  301. {
  302. header = 'Test Drive',
  303. txt = 'Allow player for test drive',
  304. params = {
  305. event = 'qb-vehicleshop:client:openIdMenu',
  306. args = {
  307. vehicle = Config.Shops[closestShop]["ShowroomVehicles"][ClosestVehicle].chosenVehicle,
  308. type = 'testDrive'
  309. }
  310. }
  311. },
  312. {
  313. header = "Sell Vehicle",
  314. txt = 'Sell vehicle to Player',
  315. params = {
  316. event = 'qb-vehicleshop:client:openIdMenu',
  317. args = {
  318. vehicle = Config.Shops[closestShop]["ShowroomVehicles"][ClosestVehicle].chosenVehicle,
  319. type = 'sellVehicle'
  320. }
  321. }
  322. },
  323. {
  324. header = 'Finance Vehicle',
  325. txt = 'Finance vehicle to Player',
  326. params = {
  327. event = 'qb-vehicleshop:client:openCustomFinance',
  328. args = {
  329. price = getVehPrice(),
  330. vehicle = Config.Shops[closestShop]["ShowroomVehicles"][ClosestVehicle].chosenVehicle
  331. }
  332. }
  333. },
  334. {
  335. header = 'Swap Vehicle',
  336. txt = 'Change currently selected vehicle',
  337. params = {
  338. event = 'qb-vehicleshop:client:vehCategories',
  339. }
  340. },
  341. }
  342. Wait(1000)
  343. end
  344. end)
  345. else
  346. insideZones[name] = false -- leave the shops zone
  347. ClosestVehicle = 1
  348. end
  349. end)
  350. end
  351.  
  352. for name, shop in pairs(Config.Shops) do
  353. if shop['Type'] == 'free-use' then
  354. createFreeUseShop(shop['Zone']['Shape'], name)
  355. elseif shop['Type'] == 'managed' then
  356. createManagedShop(shop['Zone']['Shape'], name)
  357. end
  358. end
  359.  
  360. -- Events
  361.  
  362. RegisterNetEvent('qb-vehicleshop:client:transferVehicle', function(buyerId, amount)
  363. local ped = PlayerPedId()
  364. local vehicle = GetVehiclePedIsIn(ped, false)
  365. local plate = QBCore.Functions.GetPlate(vehicle)
  366. local tcoords = GetEntityCoords(GetPlayerPed(GetPlayerFromServerId(buyerId)))
  367. if #(GetEntityCoords(ped)-tcoords) < 5.0 then
  368. TriggerServerEvent('qb-vehicleshop:server:transferVehicle', plate, buyerId, amount)
  369. else
  370. QBCore.Functions.Notify('The person you are selling to is too far away.')
  371. end
  372. end)
  373.  
  374. RegisterNetEvent('qb-vehicleshop:client:homeMenu', function()
  375. exports['qb-menu']:openMenu(vehicleMenu)
  376. end)
  377.  
  378. RegisterNetEvent('qb-vehicleshop:client:showVehOptions', function()
  379. exports['qb-menu']:openMenu(vehicleMenu)
  380. end)
  381.  
  382. RegisterNetEvent('qb-vehicleshop:client:TestDrive', function()
  383. if not inTestDrive and ClosestVehicle ~= 0 then
  384. inTestDrive = true
  385. local prevCoords = GetEntityCoords(PlayerPedId())
  386. QBCore.Functions.SpawnVehicle(Config.Shops[getShopInsideOf()]["ShowroomVehicles"][ClosestVehicle].chosenVehicle, function(veh)
  387. local closestShop = getShopInsideOf()
  388. TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1)
  389. exports['LegacyFuel']:SetFuel(veh, 100)
  390. SetVehicleNumberPlateText(veh, 'TESTDRIVE')
  391. SetEntityAsMissionEntity(veh, true, true)
  392. SetEntityHeading(veh, Config.Shops[closestShop]["VehicleSpawn"].w)
  393. TriggerEvent('vehiclekeys:client:SetOwner', QBCore.Functions.GetPlate(veh))
  394. TriggerServerEvent('qb-vehicletuning:server:SaveVehicleProps', QBCore.Functions.GetVehicleProperties(veh))
  395. testDriveVeh = veh
  396. QBCore.Functions.Notify('You have '..Config.Shops[closestShop]["TestDriveTimeLimit"]..' minutes remaining')
  397. SetTimeout(Config.Shops[closestShop]["TestDriveTimeLimit"] * 60000, function()
  398. if testDriveVeh ~= 0 then
  399. testDriveVeh = 0
  400. inTestDrive = false
  401. QBCore.Functions.DeleteVehicle(veh)
  402. SetEntityCoords(PlayerPedId(), prevCoords)
  403. QBCore.Functions.Notify('Vehicle test drive complete')
  404. end
  405. end)
  406. end, Config.Shops[getShopInsideOf()]["VehicleSpawn"], false)
  407. createTestDriveReturn()
  408. startTestDriveTimer(Config.Shops[getShopInsideOf()]["TestDriveTimeLimit"] * 60)
  409. else
  410. QBCore.Functions.Notify('Already in test drive', 'error')
  411. end
  412. end)
  413.  
  414. RegisterNetEvent('qb-vehicleshop:client:customTestDrive', function(data)
  415. if not inTestDrive then
  416. inTestDrive = true
  417. shopInsideOf = getShopInsideOf()
  418. local vehicle = data
  419. local prevCoords = GetEntityCoords(PlayerPedId())
  420. QBCore.Functions.SpawnVehicle(vehicle, function(veh)
  421. local shopInsideOf = getShopInsideOf()
  422. exports['LegacyFuel']:SetFuel(veh, 100)
  423. SetVehicleNumberPlateText(veh, 'TESTDRIVE')
  424. SetEntityAsMissionEntity(veh, true, true)
  425. SetEntityHeading(veh, Config.Shops[shopInsideOf]["VehicleSpawn"].w)
  426. TriggerEvent('vehiclekeys:client:SetOwner', QBCore.Functions.GetPlate(veh))
  427. TriggerServerEvent('qb-vehicletuning:server:SaveVehicleProps', QBCore.Functions.GetVehicleProperties(veh))
  428. testDriveVeh = veh
  429. QBCore.Functions.Notify('You have '..Config.Shops[shopInsideOf]["TestDriveTimeLimit"]..' minutes remaining')
  430. SetTimeout(Config.Shops[shopInsideOf]["TestDriveTimeLimit"] * 60000, function()
  431. if testDriveVeh ~= 0 then
  432. testDriveVeh = 0
  433. inTestDrive = false
  434. QBCore.Functions.DeleteVehicle(veh)
  435. SetEntityCoords(PlayerPedId(), prevCoords)
  436. QBCore.Functions.Notify('Vehicle test drive complete')
  437. end
  438. end)
  439. end, Config.Shops[shopInsideOf]["VehicleSpawn"], false)
  440. createTestDriveReturn()
  441. startTestDriveTimer(Config.Shops[shopInsideOf]["TestDriveTimeLimit"] * 60)
  442. else
  443. QBCore.Functions.Notify('Already in test drive', 'error')
  444. end
  445. end)
  446.  
  447. RegisterNetEvent('qb-vehicleshop:client:TestDriveReturn', function()
  448. local ped = PlayerPedId()
  449. local veh = GetVehiclePedIsIn(ped)
  450. if veh == testDriveVeh then
  451. testDriveVeh = 0
  452. inTestDrive = false
  453. QBCore.Functions.DeleteVehicle(veh)
  454. exports['qb-menu']:closeMenu()
  455. testDriveZone:destroy()
  456. else
  457. QBCore.Functions.Notify('This is not your test drive vehicle', 'error')
  458. end
  459. end)
  460.  
  461. RegisterNetEvent('qb-vehicleshop:client:vehCategories', function()
  462. local categoryMenu = {
  463. {
  464. header = '< Go Back',
  465. params = {
  466. event = 'qb-vehicleshop:client:homeMenu'
  467. }
  468. }
  469. }
  470. for k,v in pairs(Config.Shops[getShopInsideOf()]['Categories']) do
  471. categoryMenu[#categoryMenu + 1] = {
  472. header = v,
  473. params = {
  474. event = 'qb-vehicleshop:client:openVehCats',
  475. args = {
  476. catName = k
  477. }
  478. }
  479. }
  480. end
  481. exports['qb-menu']:openMenu(categoryMenu)
  482. end)
  483.  
  484. RegisterNetEvent('qb-vehicleshop:client:openVehCats', function(data)
  485. local vehicleMenu = {
  486. {
  487. header = '< Go Back',
  488. params = {
  489. event = 'qb-vehicleshop:client:vehCategories'
  490. }
  491. }
  492. }
  493. for k,v in pairs(QBCore.Shared.Vehicles) do
  494. if QBCore.Shared.Vehicles[k]["category"] == data.catName and QBCore.Shared.Vehicles[k]["shop"] == getShopInsideOf() then
  495. vehicleMenu[#vehicleMenu + 1] = {
  496. header = v.name,
  497. txt = 'Price: $'..v.price,
  498. params = {
  499. isServer = true,
  500. event = 'qb-vehicleshop:server:swapVehicle',
  501. args = {
  502. toVehicle = v.model,
  503. ClosestVehicle = ClosestVehicle,
  504. ClosestShop = getShopInsideOf()
  505. }
  506. }
  507. }
  508. end
  509. end
  510. exports['qb-menu']:openMenu(vehicleMenu)
  511. end)
  512.  
  513. RegisterNetEvent('qb-vehicleshop:client:openFinance', function(data)
  514. local dialog = exports['qb-input']:ShowInput({
  515. header = getVehBrand():upper().. ' ' ..data.buyVehicle:upper().. ' - $' ..data.price,
  516. submitText = "Submit",
  517. inputs = {
  518. {
  519. type = 'number',
  520. isRequired = true,
  521. name = 'downPayment',
  522. text = 'Down Payment Amount - Min ' ..Config.MinimumDown..'%'
  523. },
  524. {
  525. type = 'number',
  526. isRequired = true,
  527. name = 'paymentAmount',
  528. text = 'Total Payments - Min '..Config.MaximumPayments
  529. }
  530. }
  531. })
  532. if dialog then
  533. if not dialog.downPayment or not dialog.paymentAmount then return end
  534. TriggerServerEvent('qb-vehicleshop:server:financeVehicle', dialog.downPayment, dialog.paymentAmount, data.buyVehicle)
  535. end
  536. end)
  537.  
  538. RegisterNetEvent('qb-vehicleshop:client:openCustomFinance', function(data)
  539. TriggerEvent('animations:client:EmoteCommandStart', {"tablet2"})
  540. local dialog = exports['qb-input']:ShowInput({
  541. header = getVehBrand():upper().. ' ' ..data.vehicle:upper().. ' - $' ..data.price,
  542. submitText = "Submit",
  543. inputs = {
  544. {
  545. type = 'number',
  546. isRequired = true,
  547. name = 'downPayment',
  548. text = 'Down Payment Amount - Min 10%'
  549. },
  550. {
  551. type = 'number',
  552. isRequired = true,
  553. name = 'paymentAmount',
  554. text = 'Total Payments - Max '..Config.MaximumPayments
  555. },
  556. {
  557. text = "Server ID (#)",
  558. name = "playerid",
  559. type = "number",
  560. isRequired = true
  561. }
  562. }
  563. })
  564. if dialog then
  565. if not dialog.downPayment or not dialog.paymentAmount or not dialog.playerid then return end
  566. TriggerEvent('animations:client:EmoteCommandStart', {"c"})
  567. TriggerServerEvent('qb-vehicleshop:server:sellfinanceVehicle', dialog.downPayment, dialog.paymentAmount, data.vehicle, dialog.playerid)
  568. end
  569. end)
  570.  
  571. RegisterNetEvent('qb-vehicleshop:client:swapVehicle', function(data)
  572. local shopName = getShopInsideOf()
  573. if Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].chosenVehicle ~= data.toVehicle then
  574. local closestVehicle, closestDistance = QBCore.Functions.GetClosestVehicle(vector3(Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.x, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.y, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.z))
  575. if closestVehicle == 0 then return end
  576. if closestDistance < 5 then QBCore.Functions.DeleteVehicle(closestVehicle) end
  577. Wait(250)
  578. local model = GetHashKey(data.toVehicle)
  579. RequestModel(model)
  580. while not HasModelLoaded(model) do
  581. Citizen.Wait(250)
  582. end
  583. local veh = CreateVehicle(model, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.x, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.y, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.z, false, false)
  584. SetModelAsNoLongerNeeded(model)
  585. SetVehicleOnGroundProperly(veh)
  586. SetEntityInvincible(veh,true)
  587. SetEntityHeading(veh, Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].coords.w)
  588. SetVehicleDoorsLocked(veh, 3)
  589. FreezeEntityPosition(veh, true)
  590. SetVehicleNumberPlateText(veh, 'BUY ME')
  591. Config.Shops[shopName]["ShowroomVehicles"][data.ClosestVehicle].chosenVehicle = data.toVehicle
  592. end
  593. end)
  594.  
  595. RegisterNetEvent('qb-vehicleshop:client:buyShowroomVehicle', function(vehicle, plate)
  596. QBCore.Functions.SpawnVehicle(vehicle, function(veh)
  597. TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1)
  598. exports['LegacyFuel']:SetFuel(veh, 100)
  599. SetVehicleNumberPlateText(veh, plate)
  600. SetEntityHeading(veh, Config.Shops[getShopInsideOf()]["VehicleSpawn"].w)
  601. SetEntityAsMissionEntity(veh, true, true)
  602. TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(veh))
  603. TriggerServerEvent("qb-vehicletuning:server:SaveVehicleProps", QBCore.Functions.GetVehicleProperties(veh))
  604. end, Config.Shops[getShopInsideOf()]["VehicleSpawn"], true)
  605. end)
  606.  
  607. RegisterNetEvent('qb-vehicleshop:client:getVehicles', function()
  608. QBCore.Functions.TriggerCallback('qb-vehicleshop:server:getVehicles', function(vehicles)
  609. local ownedVehicles = {}
  610. for k,v in pairs(vehicles) do
  611. if v.balance then
  612. local name = QBCore.Shared.Vehicles[v.vehicle]["name"]
  613. local plate = v.plate:upper()
  614. ownedVehicles[#ownedVehicles + 1] = {
  615. header = ''..name..'',
  616. txt = 'Plate: ' ..plate,
  617. params = {
  618. event = 'qb-vehicleshop:client:getVehicleFinance',
  619. args = {
  620. vehiclePlate = plate,
  621. balance = v.balance,
  622. paymentsLeft = v.paymentsleft,
  623. paymentAmount = v.paymentamount
  624. }
  625. }
  626. }
  627. end
  628. end
  629. exports['qb-menu']:openMenu(ownedVehicles)
  630. end)
  631. end)
  632.  
  633. RegisterNetEvent('qb-vehicleshop:client:getVehicleFinance', function(data)
  634. local vehFinance = {
  635. {
  636. header = '< Go Back',
  637. params = {
  638. event = 'qb-vehicleshop:client:getVehicles'
  639. }
  640. },
  641. {
  642. isMenuHeader = true,
  643. header = 'Total Balance Remaining',
  644. txt = '$'..comma_value(data.balance)..''
  645. },
  646. {
  647. isMenuHeader = true,
  648. header = 'Total Payments Remaining',
  649. txt = ''..data.paymentsLeft..''
  650. },
  651. {
  652. isMenuHeader = true,
  653. header = 'Recurring Payment Amount',
  654. txt = '$'..comma_value(data.paymentAmount)..''
  655. },
  656. {
  657. header = 'Make a payment',
  658. params = {
  659. event = 'qb-vehicleshop:client:financePayment',
  660. args = {
  661. vehData = data,
  662. paymentsLeft = data.paymentsleft,
  663. paymentAmount = data.paymentamount
  664. }
  665. }
  666. },
  667. {
  668. header = 'Payoff vehicle',
  669. params = {
  670. isServer = true,
  671. event = 'qb-vehicleshop:server:financePaymentFull',
  672. args = {
  673. vehBalance = data.balance,
  674. vehPlate = data.vehiclePlate
  675. }
  676. }
  677. },
  678. }
  679. exports['qb-menu']:openMenu(vehFinance)
  680. end)
  681.  
  682. RegisterNetEvent('qb-vehicleshop:client:financePayment', function(data)
  683. local dialog = exports['qb-input']:ShowInput({
  684. header = 'Vehicle Payment',
  685. submitText = "Make Payment",
  686. inputs = {
  687. {
  688. type = 'number',
  689. isRequired = true,
  690. name = 'paymentAmount',
  691. text = 'Payment Amount ($)'
  692. }
  693. }
  694. })
  695. if dialog then
  696. if not dialog.paymentAmount then return end
  697. TriggerServerEvent('qb-vehicleshop:server:financePayment', dialog.paymentAmount, data.vehData)
  698. end
  699. end)
  700.  
  701. RegisterNetEvent('qb-vehicleshop:client:openIdMenu', function(data)
  702. local dialog = exports['qb-input']:ShowInput({
  703. header = QBCore.Shared.Vehicles[data.vehicle]["name"],
  704. submitText = "Submit",
  705. inputs = {
  706. {
  707. text = "Server ID (#)",
  708. name = "playerid",
  709. type = "number",
  710. isRequired = true
  711. }
  712. }
  713. })
  714. if dialog then
  715. if not dialog.playerid then return end
  716. if data.type == 'testDrive' then
  717. TriggerServerEvent('qb-vehicleshop:server:customTestDrive', data.vehicle, dialog.playerid)
  718. elseif data.type == 'sellVehicle' then
  719. TriggerServerEvent('qb-vehicleshop:server:sellShowroomVehicle', data.vehicle, dialog.playerid)
  720. end
  721. end
  722. end)
  723.  
  724. -- Threads
  725.  
  726. CreateThread(function()
  727. for k,v in pairs(Config.Shops) do
  728. if v.showBlip then
  729. local Dealer = AddBlipForCoord(Config.Shops[k]["Location"])
  730. SetBlipSprite (Dealer, 326)
  731. SetBlipDisplay(Dealer, 4)
  732. SetBlipScale (Dealer, 0.75)
  733. SetBlipAsShortRange(Dealer, true)
  734. SetBlipColour(Dealer, 3)
  735. BeginTextCommandSetBlipName("STRING")
  736. AddTextComponentSubstringPlayerName(Config.Shops[k]["ShopLabel"])
  737. EndTextCommandSetBlipName(Dealer)
  738. end
  739. end
  740. end)
  741.  
  742. CreateThread(function()
  743. local financeZone = BoxZone:Create(Config.FinanceZone, 2.0, 2.0, {
  744. name="financeZone",
  745. offset={0.0, 0.0, 0.0},
  746. scale={1.0, 1.0, 1.0},
  747. debugPoly=false,
  748. })
  749.  
  750. financeZone:onPlayerInOut(function(isPointInside)
  751. if isPointInside then
  752. exports['qb-menu']:showHeader(financeMenu)
  753. else
  754. exports['qb-menu']:closeMenu()
  755. end
  756. end)
  757. end)
  758.  
  759. CreateThread(function()
  760. for k,v in pairs(Config.Shops) do
  761. for i = 1, #Config.Shops[k]['ShowroomVehicles'] do
  762. local model = GetHashKey(Config.Shops[k]["ShowroomVehicles"][i].defaultVehicle)
  763. RequestModel(model)
  764. while not HasModelLoaded(model) do
  765. Wait(0)
  766. end
  767. local veh = CreateVehicle(model, Config.Shops[k]["ShowroomVehicles"][i].coords.x, Config.Shops[k]["ShowroomVehicles"][i].coords.y, Config.Shops[k]["ShowroomVehicles"][i].coords.z, false, false)
  768. SetModelAsNoLongerNeeded(model)
  769. SetEntityAsMissionEntity(veh, true, true)
  770. SetVehicleOnGroundProperly(veh)
  771. SetEntityInvincible(veh,true)
  772. SetVehicleDirtLevel(veh, 0.0)
  773. SetVehicleDoorsLocked(veh, 3)
  774. SetEntityHeading(veh, Config.Shops[k]["ShowroomVehicles"][i].coords.w)
  775. FreezeEntityPosition(veh,true)
  776. SetVehicleNumberPlateText(veh, 'BUY ME')
  777. end
  778.  
  779. createVehZones(k)
  780. end
  781. end)
  782.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement