├── fxmanifest.lua ├── LICENSE ├── server └── server.lua ├── config.lua ├── README.md └── client └── client.lua /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | games { 'gta5' } 3 | 4 | name "teezy-Carrental" 5 | author 'Teezy Core' 6 | description 'A Advanced Car Rental System for FiveM QBCore Framework Originally Made by NaorNC' 7 | version '1.0.0' 8 | 9 | client_scripts { 10 | 'config.lua', 11 | 'client/*.lua', 12 | } 13 | 14 | server_scripts { 15 | 'config.lua', 16 | 'server/*.lua', 17 | } 18 | 19 | lua54 'yes' -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Teezy Core 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /server/server.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | 3 | RegisterServerEvent('qb-rental:attemptPurchase', function(car, price, rentMinute, fee) 4 | local src = source 5 | local Player = QBCore.Functions.GetPlayer(src) 6 | local cash = Player.PlayerData.money.cash 7 | 8 | local total = price + fee 9 | if cash >= price then 10 | Player.Functions.RemoveMoney("cash", total, "rentals") 11 | TriggerClientEvent('qb-rental:vehiclespawn', source, car, rentMinute) 12 | TriggerClientEvent('QBCore:Notify', src, car .. " has been rented for $" .. price .. ", return it in order to receive 50% of the total costs.", "success") 13 | else 14 | TriggerClientEvent('qb-rental:attemptvehiclespawnfail', source) 15 | end 16 | end) 17 | 18 | RegisterServerEvent('qb-rental:giverentalpaperServer', function(model, plateText) 19 | local src = source 20 | local PlayerData = QBCore.Functions.GetPlayer(src) 21 | local info = { 22 | label = plateText, 23 | } 24 | PlayerData.Functions.AddItem('rentalpapers', 1, false, info) 25 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['rentalpapers'], "add") 26 | end) 27 | 28 | RegisterServerEvent('qb-rental:server:payreturn', function(model) 29 | local src = source 30 | local Player = QBCore.Functions.GetPlayer(source) 31 | for k,v in pairs(Config.vehicleList) do 32 | if string.lower(v.model) == model then 33 | local payment = v.price / 2 34 | Player.Functions.RemoveItem('rentalpapers', 1) 35 | Player.Functions.AddMoney("cash",payment,"rental-return") 36 | TriggerClientEvent('QBCore:Notify', src, "You have returned your rented vehicle and received $" .. payment .. " in return.", "success") 37 | end 38 | end 39 | end) 40 | 41 | RegisterServerEvent('qb-rental:server:notimereturn', function() 42 | local src = source 43 | local Player = QBCore.Functions.GetPlayer(source) 44 | Player.Functions.RemoveItem('rentalpapers', 1) 45 | TriggerClientEvent('QBCore:Notify', src, "Your rental time has been finished, your car was impounded by the Government", "error") 46 | end) 47 | 48 | QBCore.Functions.CreateCallback('qb-rental:server:hasrentalpapers', function(source, cb) 49 | local Player = QBCore.Functions.GetPlayer(source) 50 | local Item = Player.Functions.GetItemByName("rentalpapers") 51 | if Item ~= nil then 52 | cb(true) 53 | else 54 | cb(false) 55 | end 56 | end) -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | 3 | Config.setupMenu = 'qb-menu' -- qb-menu / nh-context 4 | Config.Debug = false -- Debug Mode 5 | Config.Blip = false -- Blip on Map 6 | Config.RentalPlateMark = "TC" -- This is a Prefix for the Plate of the Vehicle 7 | 8 | -- List of vehicles that can be rented 9 | --@param name = The name of the vehicle, this will be displayed in the menu 10 | --@param model = The model of the vehicle (https://wiki.rage.mp/index.php?title=Vehicles) 11 | --@param price = The price of the vehicle 12 | --@description = You can add as many vehicles as you want, just make sure you add a comma after the last bracket. 13 | Config.vehicleList = { 14 | { name = "Bison", model = "bison", price = 300 }, 15 | { name = "Futo", model = "Futo", price = 250 }, 16 | { name = "Coach", model = "coach", price = 400 }, 17 | { name = "Tour bus", model = "tourbus", price = 600 }, 18 | { name = "Taco", model = "taco", price = 420 }, 19 | { name = "Limo", model = "stretch", price = 1250 }, 20 | { name = "Hearse", model = "romero", price = 1300 }, 21 | { name = "Clown Car", model = "speedo2", price = 2850 }, 22 | { name = "Festival Bus", model = "pbus2", price = 4500 }, 23 | } 24 | 25 | -- Set the rental times and additonal fees 26 | --@param value = The value of the rental time 27 | --@param text = The text of the rental time, this will be displayed in the menu 28 | --@param fees = The additional fees for the rental time 29 | --@description = You can add as many rental times as you want, just make sure you add a comma after the last bracket. 30 | Config.rentalTimes = { 31 | { value = 1, text = '1 Minute', fees = 100 }, 32 | { value = 5, text = '5 Minutess', fees = 250 }, 33 | { value = 10, text = '10 Minutes', fees = 380 }, 34 | { value = 15, text = '15 Minutes', fees = 400 }, 35 | { value = 25, text = '25 Minutes', fees = 550 }, 36 | } 37 | 38 | -- Set the locations for the rental stations 39 | --@param label = The name of the rental station, this will be displayed on the map 40 | --@param coords = The coords of the rental station 41 | --@param model = The model of the ped (https://docs.fivem.net/docs/game-references/ped-models/) 42 | --@param scenario = The scenario of the ped (https://pastebin.com/raw/6mrYTdQv) 43 | --@description = You can add as many locations as you want, just make sure you add a comma after the last bracket. 44 | Config.Locations = { 45 | ["rentalstations"] = { 46 | [1] = { label = "Rental Stations", coords = vector4(-1042.35, -2727.65, 20.17, 334.69), model = `cs_carbuyer`, scenario = "WORLD_HUMAN_CLIPBOARD"}, 47 | [2] = { label = "Rental Stations", coords = vector4(462.75, -1676.62, 29.29, 5.02), model = `cs_carbuyer`, scenario = "WORLD_HUMAN_CLIPBOARD"}, 48 | [3] = { label = "Rental Stations", coords = vector4(-1442.49, -673.65, 26.53, 288.07), model = `cs_carbuyer`, scenario = "WORLD_HUMAN_CLIPBOARD"}, 49 | }, 50 | } 51 | 52 | -- Set the locations for the vehicle spawn points 53 | --@param workSpawn = The coords of the vehicle spawn point 54 | --@param heading = The heading of the vehicle spawn point 55 | Config.vehicleSpawn = { 56 | --- Los Santos International Airport 57 | [1] = { 58 | workSpawn = { 59 | coords = vector3(-1040.9, -2725.05, 20.12), 60 | heading = 239.44, 61 | }, 62 | }, 63 | -- Davis Avenue 64 | [2] = { 65 | workSpawn = { 66 | coords = vector3(460.1, -1699.62, 29.3), 67 | heading = 323.94, 68 | }, 69 | }, 70 | -- Marathon Avenue 71 | [3] = { 72 | workSpawn = { 73 | coords = vector3(-1444.12, -680.25, 26.39), 74 | heading = 122.5, 75 | }, 76 | }, 77 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Logo](https://media.discordapp.net/attachments/1020000303078199326/1114342182321655849/Teezy_Core_with_text.png) 3 | 4 | 5 | ![Script Screenshot](https://media.discordapp.net/attachments/1018054474926915676/1114372602903920650/Advanced_Car_Rental.png?width=1246&height=701) 6 | 7 | ![Visitors](https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fgithub.com%2FTeezy-Core%2Fteezy-Carrental&label=Visitors&countColor=%23263759) 8 | 9 | [DONATE HERE](https://www.buymeacoffee.com/teezycore) 10 | # Teezy Car Rental QBCore 11 | 12 | 13 | 14 | A **Advanced** Car Rental for QBCore (Nopixel Inspired) Originally Made by [NaorNC](https://github.com/NaorNC). and enhanced by **Teezy Core**. 15 | ## Installation 16 | 17 | 1. Download the script from the source. 18 | 2. Place the script in the `resources` folder of your FiveM server. 19 | 3. Add the following line to your server.cfg file: `cfx-tcd-carRental` 20 | 4. Start your FiveM server and enjoy! 21 | 22 | ## Dependencies 23 | 24 | - `qb-target` 25 | - `qb-core` 26 | - `qb-menu` 27 | - `qb-input` 28 | - optional: *menu used in the video* [jixel-menu](https://github.com/jimathy/jixel-menu) 29 | - optional: [nh-context](https://github.com/whooith/nh-context) 30 | 31 | 32 | ## Item Setup 33 | 34 | Put this on `qb-core > shared > items.lua` 35 | ``` 36 | ["rentalpapers"] = {["name"] = "rentalpapers", ["label"] = "Rental Papers", ["weight"] = 50, ["type"] = "item", ["image"] = "rentalpapers.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "This car was taken out through car rental."}, 37 | ``` 38 | 39 | Download the Item `Image` here: 40 | [rentalpapers.png](https://camo.githubusercontent.com/f4d5ba69f4e562213d609e8c53721e74f7703096f2d20869b6585cd89e9673a8/68747470733a2f2f692e6962622e636f2f73674735486b362f72656e74616c7061706572732e706e67) 41 | 42 | ![Item](https://camo.githubusercontent.com/f4d5ba69f4e562213d609e8c53721e74f7703096f2d20869b6585cd89e9673a8/68747470733a2f2f692e6962622e636f2f73674735486b362f72656e74616c7061706572732e706e67) 43 | 44 | Put it inside your `qb-inventory > html > images` same if you are using `lj-inventory` 45 | 46 | ## Inventory JavaScript Setup 47 | 48 | Inside your `qb-inventory > js > app.js` 49 | 50 | **NOTE:** Go between Line 500-600 and add the following code 51 | 52 | ``` 53 | } else if (itemData.name == "rentalpapers") { 54 | $(".item-info-title").html('

' + itemData.label + '

') 55 | $(".item-info-description").html('

Plate: '+ itemData.info.label + '

'); 56 | ``` 57 | If you did follow this correct you will see the `info` on the `rentalpapers` item 58 | 59 | ![SS](https://media.discordapp.net/attachments/1018054474926915676/1114360823972888668/image.png) 60 | 61 | **That's all for the Installations.** 62 | ## Previews 63 | 64 | [Preview 1](https://streamable.com/6cc80x) 65 | [Preview 2](https://streamable.com/il9l1n) 66 | [Preview 3](https://streamable.com/p50vks) 67 | [Preview 4](https://streamable.com/fys36g) 68 | 69 | 70 | ## Features 71 | - `Debug Mode` Some print thingy for debugging purposes and for `Debug Poly` 72 | - `Enable/Disable Blips for Rentals` 73 | - `Setup menu:` currently supported menus `(qb-menu, nh-context)` 74 | - `Rental Plate Mark` a mark on a Vehicle plate which will be the indicator of the vehicle was only for rented. 75 | - `Unlimited Vehicle to rent` just follow the instructions inside the `config.lua` 76 | - `Configurable Rental Time` just follow the instructions inside the `config.lua` 77 | - `Configurable Locations for Rent` just follow the instructions inside the `config.lua` 78 | - `Custom Ped, and Scene for Each Rental Stations` just follow the instructions inside the `config.lua` 79 | - `Configurable Vehicle Spawn` just follow the instructions inside 80 | - `Vehicle Nearby Detection` wither there is an vehicle near the spawn point of the vehicle it will notice the player 81 | - `Automatic Vehicle Deletion upon the Rental Time` Vehicle will be Automatically deleted if Rental Time was already done. 82 | 83 | ## TODOS 84 | 85 | - [ ] Add more menus support 86 | - [ ] might be supported with ESX in the future 87 | - [ ] Add Discord Logs 88 | - [ ] Add more info on the `rentalpapers` item 89 | ## License 90 | 91 | ``` 92 | MIT License 93 | 94 | Copyright (c) 2023 Lester 95 | 96 | Permission is hereby granted, free of charge, to any person obtaining a copy 97 | of this software and associated documentation files (the "Software"), to deal 98 | in the Software without restriction, including without limitation the rights 99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100 | copies of the Software, and to permit persons to whom the Software is 101 | furnished to do so, subject to the following conditions: 102 | 103 | The above copyright notice and this permission notice shall be included in all 104 | copies or substantial portions of the Software. 105 | 106 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 107 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 108 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 109 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 110 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 111 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 112 | SOFTWARE. 113 | ``` 114 | ## Feedback 115 | 116 | If you have any feedback, please reach out to me through discord `Ternology#6508` 117 | 118 | -------------------------------------------------------------------------------- /client/client.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | RegisterNetEvent('QBCore:Client:UpdateObject', function() QBCore = exports['qb-core']:GetCoreObject() end) 3 | Peds = {} 4 | Targets = {} 5 | 6 | --==== [ FUNCTIONS ] ====-- 7 | function loadAnimDict(dict) 8 | if Config.Debug then 9 | print("^5Debug^7: ^2Loading Anim Dictionary^7: '^6"..dict.."^7'") 10 | end 11 | while not HasAnimDictLoaded(dict) do 12 | RequestAnimDict(dict) Wait(5) 13 | end 14 | end 15 | 16 | function unloadAnimDict(dict) 17 | if Config.Debug then 18 | print("^5Debug^7: ^2Removing Anim Dictionary^7: '^6"..dict.."^7'") 19 | end 20 | RemoveAnimDict(dict) 21 | end 22 | 23 | function loadModel(entity) 24 | if Config.Debug then 25 | print("^5Debug^7: ^2Loading Model^7: '^6"..entity.."^7'") 26 | end 27 | while not HasModelLoaded(entity) do 28 | RequestModel(entity) Wait(5) 29 | end 30 | end 31 | 32 | function unloadModel(entity) 33 | if Config.Debug then 34 | print("^5Debug^7: ^2Removing Model^7: '^6"..entity.."^7'") 35 | end 36 | SetModelAsNoLongerNeeded(entity) 37 | end 38 | 39 | function setPed(model, coords, freeze, collision, scenario, anim) 40 | loadModel(model) 41 | local ped = CreatePed(0, model, coords.x, coords.y, coords.z-1.03, coords.w, false, false) 42 | SetEntityInvincible(ped, true) 43 | SetBlockingOfNonTemporaryEvents(ped, true) 44 | FreezeEntityPosition(ped, freeze or true) 45 | if collision then SetEntityNoCollisionEntity(ped, PlayerPedId(), false) end 46 | if scenario then TaskStartScenarioInPlace(ped, scenario, 0, true) end 47 | if anim then 48 | loadAnimDict(anim[1]) 49 | TaskPlayAnim(ped, anim[1], anim[2], 1.0, 1.0, -1, 1, 0.2, 0, 0, 0) 50 | end 51 | if Config.Debug then print("^5Debug^7: ^6Ped ^2Created for location^7: '^6"..model.."^7'") end 52 | return ped 53 | end 54 | 55 | local countdownActive = false 56 | 57 | function StartRentalCountdown(rentalTime) 58 | if countdownActive then 59 | return 60 | end 61 | countdownActive = true 62 | 63 | remainingTime = tonumber(rentalTime) * 60 64 | 65 | while remainingTime > 0 do 66 | Citizen.Wait(1000) 67 | remainingTime = remainingTime - 1 68 | 69 | exports['qb-core']:DrawText('Remaining time: ' .. remainingTime .. ' seconds', 'right') 70 | end 71 | 72 | -- Rental time expired, perform any necessary actions here 73 | countdownActive = false 74 | exports['qb-core']:HideText() 75 | TriggerEvent("qb-rental:noRemainingTime") 76 | end 77 | 78 | function StopRentalCountdown() 79 | remainingTime = 0 80 | countdownActive = false 81 | exports['qb-core']:HideText() 82 | end 83 | 84 | --==== [ END FUNCTIONS ] ====-- 85 | 86 | --==== [ EVENTS ] ====-- 87 | RegisterNetEvent("qb-rental:vehiclelist", function() 88 | for i = 1, #Config.vehicleList do 89 | if Config.Debug then print("^5Debug^7: ^6Vehicle ^2Created for location^7: '^6"..Config.vehicleList[i].model.."^7'") end 90 | if Config.setupMenu == 'nh-context' then 91 | TriggerEvent('nh-context:sendMenu', { 92 | { 93 | id = Config.vehicleList[i].model, 94 | header = Config.vehicleList[i].name, 95 | txt = "$"..Config.vehicleList[i].price..".00", 96 | params = { 97 | event = "qb-rental:attemptvehiclespawn", 98 | args = { 99 | id = Config.vehicleList[i].model, 100 | price = Config.vehicleList[i].price, 101 | } 102 | } 103 | }, 104 | }) 105 | elseif Config.setupMenu == 'qb-menu' then 106 | local MenuOptions = { 107 | { 108 | header = "Vehicle Rental", 109 | isMenuHeader = true 110 | }, 111 | } 112 | for k, v in pairs(Config.vehicleList) do 113 | 114 | 115 | MenuOptions[#MenuOptions+1] = { 116 | header = ""..v.name.."", 117 | txt = "$"..v.price..".00", 118 | params = { 119 | event = "qb-rental:attemptvehiclespawn", 120 | args = { 121 | id = v.model, 122 | price = v.price 123 | } 124 | } 125 | } 126 | end 127 | exports['qb-menu']:openMenu(MenuOptions) 128 | end 129 | end 130 | end) 131 | 132 | RegisterNetEvent("qb-rental:attemptvehiclespawn", function(vehicle) 133 | for i, v in ipairs(Config.vehicleSpawn) do 134 | if DoesEntityExist(GetClosestVehicle(v.workSpawn.coords.x, v.workSpawn.coords.y, v.workSpawn.coords.z, 3.0, 0, 70)) then 135 | QBCore.Functions.Notify("There is a vehicle nearby, please move it.", "error") 136 | return 137 | end 138 | end 139 | 140 | local dialog = exports['qb-input']:ShowInput({ 141 | header = "REDEMTION CITY REBORN", 142 | submitText = "Rent Now", 143 | inputs = { 144 | { 145 | text = "Choose Rental Time", 146 | name = "carrentaltime", 147 | type = "select", 148 | options = Config.rentalTimes, 149 | default = 1, 150 | } 151 | }, 152 | }) 153 | 154 | if dialog ~= nil then 155 | local selectedValue = tonumber(dialog.carrentaltime) 156 | local selectedOption = nil 157 | 158 | for _, option in ipairs(Config.rentalTimes) do 159 | if option.value == selectedValue then 160 | selectedOption = option 161 | break 162 | end 163 | end 164 | 165 | if selectedOption ~= nil then 166 | local selectedFee = selectedOption.fees 167 | TriggerServerEvent("qb-rental:attemptPurchase", vehicle.id, vehicle.price, selectedValue, selectedFee) 168 | else 169 | print("Invalid rental time selected.") 170 | end 171 | else 172 | print("Rental dialog was canceled.") 173 | end 174 | 175 | end) 176 | 177 | RegisterNetEvent("qb-rental:attemptvehiclespawnfail", function() 178 | QBCore.Functions.Notify("Not enough money.", "error") 179 | end) 180 | 181 | local PlayerName = nil 182 | 183 | RegisterNetEvent("qb-rental:returnvehicle", function() 184 | local car = GetVehiclePedIsIn(PlayerPedId(),true) 185 | 186 | if car ~= 0 then 187 | local plate = GetVehicleNumberPlateText(car) 188 | local vehname = string.lower(GetDisplayNameFromVehicleModel(GetEntityModel(car))) 189 | if string.find(tostring(plate), Config.RentalPlateMark) then 190 | QBCore.Functions.TriggerCallback('qb-rental:server:hasrentalpapers', function(HasItem) 191 | if HasItem then 192 | TriggerServerEvent('qb-rental:server:payreturn',vehname) 193 | QBCore.Functions.DeleteVehicle(car) 194 | StopRentalCountdown() 195 | else 196 | QBCore.Functions.Notify("I cannot take a vehicle without its papers.", "error") 197 | end 198 | end) 199 | else 200 | QBCore.Functions.Notify("This is not a rented vehicle.", "error") 201 | end 202 | 203 | else 204 | QBCore.Functions.Notify("I don't see any rented vehicle, make sure its nearby.", "error") 205 | end 206 | end) 207 | 208 | RegisterNetEvent('qb-rental:noRemainingTime', function() 209 | local car = GetVehiclePedIsIn(PlayerPedId(), true) 210 | 211 | if car ~= 0 then 212 | local plate = GetVehicleNumberPlateText(car) 213 | if string.find(tostring(plate), Config.RentalPlateMark) then 214 | QBCore.Functions.TriggerCallback('qb-rental:server:hasrentalpapers', function(HasItem) 215 | if HasItem then 216 | TriggerServerEvent('qb-rental:server:notimereturn') 217 | QBCore.Functions.DeleteVehicle(car) 218 | StopRentalCountdown() 219 | end 220 | end) 221 | end 222 | end 223 | end) 224 | 225 | RegisterNetEvent("qb-rental:vehiclespawn", function(data, minute) 226 | local model = data 227 | 228 | local closestDist = 10000 229 | local closestSpawn = nil 230 | local pcoords = GetEntityCoords(PlayerPedId()) 231 | local CurrentPlate = nil 232 | 233 | for i, v in ipairs(Config.vehicleSpawn) do 234 | local dist = #(v.workSpawn.coords - pcoords) 235 | 236 | if dist < closestDist then 237 | closestDist = dist 238 | closestSpawn = v.workSpawn 239 | end 240 | end 241 | 242 | RequestModel(model) 243 | while not HasModelLoaded(model) do 244 | Citizen.Wait(0) 245 | end 246 | SetModelAsNoLongerNeeded(model) 247 | 248 | QBCore.Functions.SpawnVehicle(model, function(veh) 249 | SetVehicleNumberPlateText(veh, Config.RentalPlateMark..tostring(math.random(1000, 9999))) 250 | SetEntityHeading(veh, closestSpawn.heading) 251 | exports['LegacyFuel']:SetFuel(veh, 100.0) 252 | TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1) 253 | SetEntityAsMissionEntity(veh, true, true) 254 | TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(veh)) 255 | SetVehicleEngineOn(veh, true, true) 256 | CurrentPlate = QBCore.Functions.GetPlate(veh) 257 | end, closestSpawn.coords, true) 258 | 259 | TriggerServerEvent("qb-rental:giverentalpaperServer", model, CurrentPlate) 260 | StartRentalCountdown(minute) 261 | if Config.Debug then print("^5Debug^7: ^6Vehicle ^2Spawned^7: '^6"..model.."^7'".." ^6Plate^7: '^6"..CurrentPlate.."^7'") end 262 | local timeout = 10 263 | while not NetworkDoesEntityExistWithNetworkId(veh) and timeout > 0 do 264 | timeout = timeout - 1 265 | Wait(1000) 266 | end 267 | end) 268 | 269 | --==== [ END OF EVENTS ] ====-- 270 | 271 | --==== [ THREADS ] ====-- 272 | CreateThread(function() 273 | for _, rental in pairs(Config.Locations["rentalstations"]) do 274 | if Config.Debug then print("^5Debug^7: ^6Blip ^2Created for location^7: '^6"..rental.label.."^7'") end 275 | if Config.Blip then 276 | local blip = AddBlipForCoord(rental.coords.x, rental.coords.y, rental.coords.z) 277 | SetBlipSprite(blip, 326) 278 | SetBlipAsShortRange(blip, true) 279 | SetBlipScale(blip, 0.5) 280 | SetBlipColour(blip, 5) 281 | BeginTextCommandSetBlipName("STRING") 282 | AddTextComponentString(rental.label) 283 | EndTextCommandSetBlipName(blip) 284 | end 285 | end 286 | end) 287 | 288 | CreateThread(function() 289 | for _, rental in pairs(Config.Locations["rentalstations"]) do 290 | Peds[#Peds+1] = setPed(rental.model, rental.coords, true, false, rental.scenario) 291 | if Config.Debug then print("^5Debug^7: ^6Ped ^2Created for location^7: '^6"..rental.label.."^7'") end 292 | Targets['rental'.._] = exports['qb-target']:AddCircleZone("rental".._, rental.coords, 1.0, { 293 | name = "rental".._, 294 | debugPoly = Config.Debug, 295 | useZ = true, 296 | }, { 297 | options = { 298 | { 299 | event = "qb-rental:vehiclelist", 300 | icon = "fas fa-circle", 301 | label = "Rent vehicle", 302 | }, 303 | { 304 | event = "qb-rental:returnvehicle", 305 | icon = "fas fa-circle", 306 | label = "Return Vehicle (Receive Back 50% of original price)", 307 | }, 308 | }, 309 | distance = 3.5 310 | }) 311 | end 312 | end) 313 | 314 | --==== [ END OF THREADS ] ====-- 315 | 316 | AddEventHandler('onResourceStop', function(resource) 317 | if resource == GetCurrentResourceName() then end 318 | for k in pairs(Peds) do DeleteEntity(Peds[k]) end 319 | for k in pairs(Targets) do exports['qb-target']:RemoveZone(k) end 320 | exports['qb-core']:HideText() 321 | end) --------------------------------------------------------------------------------