├── fxmanifest.lua ├── config.lua ├── README.md ├── server.lua ├── client.lua └── warmenu.lua /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | author 'Squizer#3020' 5 | description 'Script that allows you to borrow vehicles.' 6 | version '1.0.0' 7 | 8 | client_scripts { 9 | 'warmenu.lua', 10 | 'config.lua', 11 | 'client.lua' 12 | } 13 | 14 | server_scripts { 15 | 'config.lua', 16 | 'server.lua' 17 | } -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | 3 | Config.InsurancePrice = 1000 4 | Config.DownPayment = 3500 5 | Config.ExtraChargePerMinute = 500 6 | 7 | Config.Points = { 8 | { 9 | Pos = vector3(-985.3989,-2707.436,13.8307), 10 | SpawnPoint = vector3(-985.3989,-2707.436,13.8307), 11 | Vehicles = { 12 | { 13 | model = 'issi2', 14 | price = 150, 15 | }, 16 | { 17 | model = 'cogcabrio', 18 | price = 250, 19 | }, 20 | { 21 | model = 'bagger', 22 | price = 75, 23 | }, 24 | { 25 | model = 'rentalbus', 26 | price = 320, 27 | }, 28 | { 29 | model = 'tribike3', 30 | price = 25, 31 | } 32 | } 33 | }, 34 | { 35 | Pos = vector3(211.2574,-1379.5165,30.5875), 36 | SpawnPoint = vector3(219.0401,-1380.4989,30.5514), 37 | Vehicles = { 38 | { 39 | model = 'issi2', 40 | price = 150, 41 | }, 42 | { 43 | model = 'cogcabrio', 44 | price = 250, 45 | }, 46 | { 47 | model = 'bagger', 48 | price = 75, 49 | }, 50 | { 51 | model = 'rentalbus', 52 | price = 320, 53 | }, 54 | { 55 | model = 'tribike3', 56 | price = 25, 57 | } 58 | } 59 | }, 60 | { 61 | Pos = vector3(-249.0248,-954.9617,31.22), 62 | SpawnPoint = vector3(-258.9018,-993.5417,29.951), 63 | Vehicles = { 64 | { 65 | model = 'issi2', 66 | price = 150, 67 | }, 68 | { 69 | model = 'cogcabrio', 70 | price = 250, 71 | }, 72 | { 73 | model = 'bagger', 74 | price = 75, 75 | }, 76 | { 77 | model = 'rentalbus', 78 | price = 320, 79 | }, 80 | { 81 | model = 'tribike3', 82 | price = 25, 83 | } 84 | } 85 | }, 86 | { 87 | Pos = vector3(1852.7104,2593.9482,45.672), 88 | SpawnPoint = vector3(1867.6857,2599.4282,45.672), 89 | Vehicles = { 90 | { 91 | model = 'issi2', 92 | price = 150, 93 | }, 94 | { 95 | model = 'cogcabrio', 96 | price = 250, 97 | }, 98 | { 99 | model = 'bagger', 100 | price = 75, 101 | }, 102 | { 103 | model = 'rentalbus', 104 | price = 320, 105 | }, 106 | { 107 | model = 'tribike3', 108 | price = 25, 109 | } 110 | } 111 | }, 112 | } 113 | 114 | Config.ReturnPoints = { 115 | vector3(1871.1001,2608.6328,45.672), 116 | vector3(-263.0754,-990.73,30.457), 117 | vector3(915.2678,-190.6824,73.2665), 118 | vector3(242.7683,-1411.8146,30.5671), 119 | vector3(366.9097,-952.8362,29.4442), 120 | vector3(1855.3997,2625.0098,45.6678), 121 | vector3(-290.9992,-127.1658,44.3788), 122 | vector3(-1134.4578,-1585.7444,4.3294), 123 | } 124 | 125 | Config.RentalTimes = { 126 | '5 min', '10 min', '15 min', '20 min', '25 min', '30 min' 127 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SQZ_RENTAL SCRIPT 2 | 3 | Advanced vehicle rental system which comes with insurance and custom length for renting any type of vehicle. 4 | 5 | 6 |
7 | 8 | # 🌐 **Host Smarter with Fusiora.com!** 🚀 9 | 10 | Fusiora Logo 11 | 12 | 🖥️ **Premium hardware** in **Netherlands**, **Miami**, & **Germany**. 13 | 🛡️ **DDoS protection** for **any game**. 14 | 💸 Use **`CODELY`** for **10% OFF**! 15 | 16 | ## 🔗 [**Start Hosting Now**](https://fusiora.com) 17 | 18 |
19 | 20 | # Features 21 | - Rent any type of vehicle 22 | - Optimalization 23 | - Unlimited delivery/take points 24 | - Pay insurance (if not paid, you will be charged for damage cause to the vehicle) 25 | - Choose time you wanna rent the vehicle for 26 | 27 | # Instalation 28 | - Drop the script into your resources folder and start it in your `server.cfg` 29 | - Configure the config, eventualy change the locales and you are done! 30 | - Yes, thats actually all 31 | 32 | # Other Scripts made by Squizer 33 | * [sqz_anticheat](https://forum.cfx.re/t/anticheat-revolutionary-anticheat/4802102) - Higly effective cheap FiveM anticheat 34 | * [sqz_unijob](https://forum.cfx.re/t/esx-sqz-unijob-advanced-system-for-easy-adding-jobs/2100467) - Script for adding multiple jobs into 1 script just by edditing config 35 | * [sqz_drugs](https://forum.cfx.re/t/esx-sqz-drugs-advanced-drug-system/2167691) - Complete system for drugs, planting, harvesting, watering, processing and dealing drugs 36 | * [sqz_duty](https://forum.cfx.re/t/release-esx-sqz-duty-advanced-duty-script/3354791) - Advanced duty system which counts time spent in duty 37 | * [sqz_robbery](https://forum.cfx.re/t/release-sqz-robbery-advanced-robbery-script/4773035) - All in one robbery system 38 | * [sqz_chatenhancements](https://forum.cfx.re/t/sqz-chatenhancements-status-here-roll-commands/4804562) - Commands /status, /here and /roll for your chat 39 | * [sqz_switchjob](https://github.com/czsquizer/switchjob) - Script for switching and having multiple jobs 40 | * [sqz_carmenu](https://github.com/czsquizer/sqz_carmenu) - Script for all the car features you would ever need 41 | * [sqz_hospital](https://github.com/czsquizer/sqz_hospital) - Script that allows player heal themselves in the hospital in case there are no doctors on your server 42 | * [sqz_banlist](https://github.com/czsquizer/sqz_banlist) - List with cheaters with mod menu opened. Prevent cheating on your server! 43 | * [sqz_carkeys](https://github.com/czsquizer/sqz_carkeys) - FiveM vehicle Keys scripts with giving and saving keys in the database. 44 | * [sqz_rental](https://github.com/czsquizer/sqz_rental) - Quality rental system with all types of vehicles and an insurace! 45 | * [sqz_itemwhitelist](https://github.com/czsquizer/sqz_itemwhitelist) - Prop and vehicle whitelist/blacklist to prevent hackers spamming your server with entities 46 | * [others](https://github.com/czsquizer?tab=repositories) - You can find there my forks of other scripts, check them as well 47 | 48 | ### Preview 49 | [YouTube](https://www.youtube.com/watch?v=uuEVB5mvpcc) 50 |
51 | 52 | __You can read the docs here__ 53 | [![Docs](https://img.shields.io/badge/docs-passing-brightgreen)](https://docs.squizer.cz) 54 | 55 | # Visit Squizer's "social media" 56 | * [Tebex](https://sqz.tebex.io/) 57 | * [Page](https://squizer.cz) 58 | * [Cfx.re Forum](https://forum.cfx.re/u/squizer/) 59 | * [Discord](https://discord.gg/FVXAu2F) 60 | * [GitHub](https://github.com/czsquizer/) 61 | ### Made by Squizer#3020 62 | ### You can edit this script as yours, but do NOT take it as yours, republish it, resell it as Mr. Cryzysek (ProjectX server owner) did it with sqz_switchjob. -------------------------------------------------------------------------------- /server.lua: -------------------------------------------------------------------------------- 1 | local rentedVehicles = {} 2 | TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) 3 | 4 | RegisterNetEvent('sqz_carrental:RentVehicle') 5 | AddEventHandler('sqz_carrental:RentVehicle', function(model, insurance, price, time, rentalIndex) 6 | time = time:gsub('min', '') 7 | time = tonumber(time) 8 | local xPlayer = ESX.GetPlayerFromId(source) 9 | 10 | if xPlayer.getMoney() >= price + Config.DownPayment then 11 | xPlayer.removeMoney(price + Config.DownPayment) 12 | xPlayer.showNotification('You have paid '..price..'$') 13 | xPlayer.showNotification('You have paid '..Config.DownPayment..'$ as a down payment') 14 | TriggerClientEvent('sqz_carrental:SpawnVehicle', source, model, insurance, price, time, rentalIndex) 15 | elseif xPlayer.getAccount('bank').money >= price + Config.DownPayment then 16 | xPlayer.removeAccountMoney('bank', price + Config.DownPayment) 17 | xPlayer.showNotification('You have paid '..Config.DownPayment..'$ as a down payment from your bank account') 18 | xPlayer.showNotification('You have paid '..price..'$ from your bank account') 19 | TriggerClientEvent('sqz_carrental:SpawnVehicle', source, model, insurance, price, time, rentalIndex) 20 | else 21 | xPlayer.showNotification('You can not afford renting this vehicle') 22 | end 23 | end) 24 | 25 | RegisterNetEvent('sqz_carrental:VehicleSpawned') 26 | AddEventHandler('sqz_carrental:VehicleSpawned', function(plate, insurance, time, netId) 27 | local _source = source 28 | local xPlayer = ESX.GetPlayerFromId(_source) 29 | if not rentedVehicles[plate] then 30 | rentedVehicles[plate] = { 31 | owner = xPlayer.identifier, 32 | insurance = insurance, 33 | netId = netId, 34 | downPayment = Config.DownPayment 35 | } 36 | SetTimeout(time * 60 * 1000 + 5000, function() 37 | local plate = GetVehicleNumberPlateText(NetworkGetEntityFromNetworkId(netId)) 38 | if rentedVehicles[plate] then 39 | if GetPlayerPing(rentedVehicles[plate].owner) > 5 then 40 | Citizen.CreateThread(function() 41 | 42 | while true do 43 | Wait(1000 * 60) 44 | if rentedVehicles[plate].downPayment >= Config.ExtraChargePerMinute then 45 | rentedVehicles[plate].downPayment = rentedVehicles[plate].downPayment - Config.ExtraChargePerMinute 46 | else 47 | if ESX.GetPlayerFromId(_source) then 48 | xPlayer.showNotification('The deposit will not be refunded, because you have not returned the vehicle') 49 | xPlayer.showNotification('The vehicle has been impounded') 50 | end 51 | DeleteEntity(NetworkGetEntityFromNetworkId(netId)) 52 | rentedVehicles[plate] = nil 53 | end 54 | end 55 | end) 56 | else 57 | rentedVehicles[plate] = nil 58 | DeleteEntity(NetworkGetEntityFromNetworkId(netId)) 59 | end 60 | end 61 | end) 62 | end 63 | end) 64 | 65 | RegisterNetEvent('sqz_carrental:ReturnVehicle') 66 | AddEventHandler('sqz_carrental:ReturnVehicle', function(plate, damageIndex) 67 | local xPlayer = ESX.GetPlayerFromId(source) 68 | if not rentedVehicles[plate] then 69 | xPlayer.showNotification('You can not return this vehicle because this one has not been rented.') 70 | return 71 | end 72 | 73 | if rentedVehicles[plate].owner ~= xPlayer.identifier then 74 | xPlayer.showNotification('You can not return this vehicle because you are not borrower.') 75 | return 76 | end 77 | 78 | if rentedVehicles[plate].insurance then 79 | damageIndex = 1 80 | end 81 | 82 | local moneyToGive = math.floor(rentedVehicles[plate].downPayment * damageIndex) 83 | 84 | if damageIndex < 1 then 85 | local reducedBy = Config.DownPayment - Config.DownPayment * damageIndex 86 | xPlayer.showNotification('Down payment you should receive has been lowered by '..reducedBy..'$ because you have returned the vehicle damaged') 87 | end 88 | 89 | xPlayer.addAccountMoney('bank', moneyToGive) 90 | xPlayer.showNotification('The down payment of amount '..moneyToGive..'$ has been returned you.') 91 | TaskLeaveVehicle(GetPlayerPed(source), NetworkGetEntityFromNetworkId(rentedVehicles[plate].netId), 0) 92 | Wait(1700) 93 | DeleteEntity(NetworkGetEntityFromNetworkId(rentedVehicles[plate].netId)) 94 | rentedVehicles[plate] = nil 95 | TriggerClientEvent('sqz_carrental:VehicleSuccessfulyReturned', xPlayer.source) 96 | end) -------------------------------------------------------------------------------- /client.lua: -------------------------------------------------------------------------------- 1 | local rentalTimer = 0 2 | local lastLocalVehicle 3 | 4 | Citizen.CreateThread(function() 5 | AddTextEntry('carRental', 'Vehicle Rental') 6 | AddTextEntry('carRentalClose', '~INPUT_PICKUP~ Vehicle Rental') 7 | while true do 8 | Wait(0) 9 | local letSleep = true 10 | if rentalTimer == 0 then 11 | local pedCoords = GetEntityCoords(PlayerPedId()) 12 | for k, v in pairs(Config.Points) do 13 | local dist = #(pedCoords - v.Pos) 14 | if dist < 1.5 and not IsPedInAnyVehicle(PlayerPedId()) then 15 | letSleep = false 16 | BeginTextCommandDisplayHelp('carRentalClose') 17 | EndTextCommandDisplayHelp(1, 0, 0, 0) 18 | SetFloatingHelpTextWorldPosition(0, v.Pos) 19 | 20 | if IsControlJustPressed(0, 38) then 21 | OpenCarRental(k) 22 | Wait(500) 23 | end 24 | elseif dist < 5 and not IsPedInAnyVehicle(PlayerPedId()) then 25 | letSleep = false 26 | BeginTextCommandDisplayHelp('carRental') 27 | EndTextCommandDisplayHelp(1, 0, 0, 0) 28 | SetFloatingHelpTextWorldPosition(0, v.Pos) 29 | end 30 | end 31 | else 32 | Wait(1000) 33 | end 34 | 35 | if letSleep then 36 | Wait(500) 37 | end 38 | end 39 | end) 40 | 41 | WarMenu.CreateMenu('carRental', 'Vehicle Rental') 42 | 43 | function OpenCarRental(index) 44 | WarMenu.OpenMenu('carRental') 45 | local price = 0 46 | local vehicleIndex = 1 47 | local rentalTimeIndex = 1 48 | local vehiclesToRent = {} 49 | 50 | 51 | for k, v in pairs(Config.Points[index].Vehicles) do 52 | table.insert(vehiclesToRent, v.model) 53 | end 54 | 55 | SpawnLocalVehicle(vehiclesToRent[1], Config.Points[index].SpawnPoint) 56 | 57 | while true do 58 | Wait(0) 59 | if WarMenu.Begin('carRental') then 60 | 61 | local _, vehicleId = WarMenu.ComboBox('Select Vehicle', vehiclesToRent, vehicleIndex) 62 | if vehicleIndex ~= vehicleId then 63 | vehicleIndex = vehicleId 64 | if DoesEntityExist(lastLocalVehicle) then 65 | DeleteEntity(lastLocalVehicle) 66 | lastLocalVehicle = nil 67 | FreezeEntityPosition(PlayerPedId(), false) 68 | SetEntityInvincible(PlayerPedId(), false) 69 | SetEntityCoords(PlayerPedId(), Config.Points[index].Pos) 70 | end 71 | SpawnLocalVehicle(vehiclesToRent[vehicleId], Config.Points[index].SpawnPoint) 72 | end 73 | 74 | local _, totalTime = WarMenu.ComboBox('Vehicle Rental Time', Config.RentalTimes, rentalTimeIndex) 75 | if rentalTimeIndex ~= totalTime then 76 | rentalTimeIndex = totalTime 77 | end 78 | 79 | if WarMenu.CheckBox('Insurance - '..Config.InsurancePrice..'$', insurance) then 80 | insurance = not insurance 81 | end 82 | 83 | if WarMenu.IsItemHovered() then 84 | WarMenu.ToolTip('In case you damage the car, you will pay no additional fees') 85 | end 86 | 87 | price = Config.Points[index].Vehicles[vehicleIndex].price 88 | price = price * rentalTimeIndex 89 | if insurance then 90 | price = price + Config.InsurancePrice 91 | end 92 | 93 | if WarMenu.Button('Rent Vehicle', price..'$') then 94 | if DoesEntityExist(lastLocalVehicle) then 95 | DeleteEntity(lastLocalVehicle) 96 | lastLocalVehicle = nil 97 | FreezeEntityPosition(PlayerPedId(), false) 98 | SetEntityInvincible(PlayerPedId(), false) 99 | SetEntityCoords(PlayerPedId(), Config.Points[index].Pos) 100 | end 101 | TriggerServerEvent('sqz_carrental:RentVehicle', vehiclesToRent[vehicleId], insurance, price, Config.RentalTimes[rentalTimeIndex], index) 102 | return 103 | end 104 | 105 | 106 | WarMenu.End() 107 | else 108 | if DoesEntityExist(lastLocalVehicle) then 109 | DeleteEntity(lastLocalVehicle) 110 | lastLocalVehicle = nil 111 | FreezeEntityPosition(PlayerPedId(), false) 112 | SetEntityInvincible(PlayerPedId(), false) 113 | SetEntityCoords(PlayerPedId(), Config.Points[index].Pos) 114 | end 115 | return 116 | end 117 | end 118 | 119 | end 120 | 121 | function SpawnLocalVehicle(model, coords) 122 | model = GetHashKey(model) 123 | 124 | RequestModel(model) 125 | while not HasModelLoaded(model) do 126 | Wait(0) 127 | end 128 | 129 | lastLocalVehicle = CreateVehicle(model, coords, GetEntityHeading(PlayerPedId()), true, false) 130 | 131 | SetEntityAsMissionEntity(lastLocalVehicle, true, true) 132 | SetVehicleOnGroundProperly(lastLocalVehicle) 133 | FreezeEntityPosition(lastLocalVehicle, true) 134 | SetEntityInvincible(lastLocalVehicle, true) 135 | SetVehicleDoorsLocked(lastLocalVehicle, 2) 136 | TaskWarpPedIntoVehicle(PlayerPedId(), lastLocalVehicle, -1) 137 | FreezeEntityPosition(PlayerPedId(), true) 138 | SetEntityInvincible(PlayerPedId(), true) 139 | end 140 | 141 | Citizen.CreateThread(function() 142 | 143 | for k, v in pairs(Config.Points) do 144 | local blip = AddBlipForCoord(v.Pos) 145 | 146 | SetBlipSprite (blip, 147) 147 | SetBlipDisplay(blip, 4) 148 | SetBlipScale (blip, 0.8) 149 | SetBlipColour (blip, 24) 150 | SetBlipAsShortRange(blip, true) 151 | SetBlipHighDetail(blip, true) 152 | 153 | BeginTextCommandSetBlipName('STRING') 154 | AddTextComponentSubstringPlayerName('Vehicle Rental') 155 | EndTextCommandSetBlipName(blip) 156 | end 157 | 158 | end) 159 | 160 | local returnBlips = {} 161 | 162 | function createReturnBlips() 163 | 164 | for k, v in pairs(Config.ReturnPoints) do 165 | local blip = AddBlipForCoord(v) 166 | 167 | SetBlipSprite (blip, 527) 168 | SetBlipDisplay(blip, 4) 169 | SetBlipScale (blip, 0.8) 170 | SetBlipColour (blip, 65) 171 | SetBlipAsShortRange(blip, true) 172 | SetBlipHighDetail(blip, true) 173 | 174 | BeginTextCommandSetBlipName('STRING') 175 | AddTextComponentSubstringPlayerName('Vehicle Return Point') 176 | EndTextCommandSetBlipName(blip) 177 | table.insert(returnBlips, blip) 178 | end 179 | 180 | end 181 | 182 | RegisterNetEvent('sqz_carrental:SpawnVehicle') 183 | AddEventHandler('sqz_carrental:SpawnVehicle', function(model, insurance, price, time, rentalIndex) 184 | model = GetHashKey(model) 185 | 186 | RequestModel(model) 187 | 188 | while not HasModelLoaded(model) do 189 | Wait(10) 190 | end 191 | 192 | local vehicle = CreateVehicle(model, Config.Points[rentalIndex].SpawnPoint, GetEntityHeading(PlayerPedId()), true, false) 193 | while not DoesEntityExist(vehicle) do 194 | Wait(10) 195 | end 196 | local netId = VehToNet(vehicle) 197 | SetNetworkIdCanMigrate(netId, false) 198 | SetEntityAsMissionEntity(vehicle, true, true) 199 | 200 | TaskWarpPedIntoVehicle(PlayerPedId(), vehicle, -1) 201 | 202 | TriggerServerEvent('sqz_carrental:VehicleSpawned', GetVehicleNumberPlateText(vehicle), insurance, time, netId) 203 | 204 | rentalTimer = time * 60 205 | 206 | createReturnBlips() 207 | 208 | startTimer() 209 | end) 210 | 211 | function disp_time(time) 212 | local minutes = math.floor((time%3600/60)) 213 | local seconds = math.floor((time%60)) 214 | return string.format("%02dm %02ds",minutes,seconds) 215 | end 216 | 217 | function startTimer() 218 | Citizen.CreateThread(function() 219 | Citizen.CreateThread(function() 220 | while rentalTimer>0 do 221 | rentalTimer=rentalTimer-1 222 | Citizen.Wait(1000) 223 | end 224 | end) 225 | while rentalTimer>0 do 226 | Citizen.Wait(0) 227 | SetTextFont(4) 228 | SetTextScale(0.45, 0.45) 229 | SetTextColour(185, 185, 185, 255) 230 | SetTextDropshadow(0, 0, 0, 0, 255) 231 | SetTextEdge(1, 0, 0, 0, 255) 232 | SetTextDropShadow() 233 | SetTextOutline() 234 | BeginTextCommandDisplayText('STRING') 235 | AddTextComponentSubstringPlayerName(disp_time(rentalTimer).." - Rental Time Remaining") 236 | EndTextCommandDisplayText(0.05, 0.55) 237 | end 238 | end) 239 | end 240 | 241 | Citizen.CreateThread(function() 242 | AddTextEntry('carReturn', 'Vehicle return point') 243 | AddTextEntry('carReturnClose', '~INPUT_PICKUP~ Return Vehicle') 244 | while true do 245 | Wait(0) 246 | if rentalTimer > 0 then 247 | local letSleep = true 248 | local pedCoords = GetEntityCoords(PlayerPedId()) 249 | for k, v in pairs(Config.ReturnPoints) do 250 | local dist = #(v - pedCoords) 251 | if dist < 2.5 and IsPedInAnyVehicle(PlayerPedId()) then 252 | letSleep = false 253 | BeginTextCommandDisplayHelp('carReturnClose') 254 | EndTextCommandDisplayHelp(1, 0, 0, 0) 255 | SetFloatingHelpTextWorldPosition(0, v) 256 | 257 | if IsControlJustPressed(0, 38) then 258 | ReturnVehicle() 259 | Wait(2000) 260 | end 261 | elseif dist < 10 and IsPedInAnyVehicle(PlayerPedId()) then 262 | letSleep = false 263 | BeginTextCommandDisplayHelp('carReturn') 264 | EndTextCommandDisplayHelp(1, 0, 0, 0) 265 | SetFloatingHelpTextWorldPosition(0, v) 266 | end 267 | end 268 | if letSleep then 269 | Wait(500) 270 | end 271 | else 272 | Wait(100) 273 | end 274 | end 275 | 276 | end) 277 | 278 | function ReturnVehicle() 279 | 280 | local vehicle = GetVehiclePedIsIn(PlayerPedId()) 281 | 282 | local health = (GetVehicleEngineHealth(vehicle) + GetVehicleBodyHealth(vehicle)) / 2 283 | TriggerServerEvent('sqz_carrental:ReturnVehicle', GetVehicleNumberPlateText(vehicle), health/1000) 284 | end 285 | 286 | RegisterNetEvent('sqz_carrental:VehicleSuccessfulyReturned') 287 | AddEventHandler('sqz_carrental:VehicleSuccessfulyReturned', function() 288 | 289 | rentalTimer = 0 290 | local sec = 3 291 | local scaleform = RequestScaleformMovie('MP_BIG_MESSAGE_FREEMODE') 292 | 293 | for i=1, #returnBlips do 294 | if DoesBlipExist(returnBlips[i]) then 295 | RemoveBlip(returnBlips[i]) 296 | end 297 | end 298 | 299 | while not HasScaleformMovieLoaded(scaleform) do 300 | Citizen.Wait(0) 301 | end 302 | 303 | BeginScaleformMovieMethod(scaleform, 'SHOW_SHARD_WASTED_MP_MESSAGE') 304 | PushScaleformMovieMethodParameterString('Vehicle Rental') 305 | PushScaleformMovieMethodParameterString('Vehicle has been successfuly returned') 306 | EndScaleformMovieMethod() 307 | 308 | while sec > 0 do 309 | Citizen.Wait(1) 310 | sec = sec - 0.01 311 | 312 | DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255) 313 | end 314 | 315 | SetScaleformMovieAsNoLongerNeeded(scaleform) 316 | end) -------------------------------------------------------------------------------- /warmenu.lua: -------------------------------------------------------------------------------- 1 | WarMenu = { } 2 | WarMenu.__index = WarMenu 3 | 4 | -- Deprecated 5 | WarMenu.debug = false 6 | function WarMenu.SetDebugEnabled(enabled) 7 | end 8 | function WarMenu.IsDebugEnabled() 9 | return false 10 | end 11 | --- 12 | 13 | local menus = { } 14 | local keys = { down = 187, up = 188, left = 189, right = 190, select = 191, back = 194 } 15 | local optionCount = 0 16 | 17 | local currentKey = nil 18 | local currentMenu = nil 19 | 20 | local toolTipWidth = 0.153 21 | 22 | local spriteWidth = 0.027 23 | local spriteHeight = spriteWidth * GetAspectRatio() 24 | 25 | local titleHeight = 0.101 26 | local titleYOffset = 0.021 27 | local titleFont = 1 28 | local titleScale = 1.0 29 | 30 | local buttonHeight = 0.038 31 | local buttonFont = 0 32 | local buttonScale = 0.365 33 | local buttonTextXOffset = 0.005 34 | local buttonTextYOffset = 0.005 35 | local buttonSpriteXOffset = 0.002 36 | local buttonSpriteYOffset = 0.005 37 | 38 | local defaultStyle = { 39 | x = 0.0175, 40 | y = 0.025, 41 | width = 0.23, 42 | maxOptionCountOnScreen = 10, 43 | titleColor = { 0, 0, 0, 255 }, 44 | titleBackgroundColor = { 245, 127, 23, 255 }, 45 | titleBackgroundSprite = nil, 46 | subTitleColor = { 245, 127, 23, 255 }, 47 | textColor = { 255, 255, 255, 255 }, 48 | subTextColor = { 189, 189, 189, 255 }, 49 | focusTextColor = { 0, 0, 0, 255 }, 50 | focusColor = { 245, 245, 245, 255 }, 51 | backgroundColor = { 0, 0, 0, 160 }, 52 | subTitleBackgroundColor = { 0, 0, 0, 255 }, 53 | buttonPressedSound = { name = 'SELECT', set = 'HUD_FRONTEND_DEFAULT_SOUNDSET' }, --https://pastebin.com/0neZdsZ5 54 | } 55 | 56 | local function setMenuProperty(id, property, value) 57 | if not id then 58 | return 59 | end 60 | 61 | local menu = menus[id] 62 | if menu then 63 | menu[property] = value 64 | end 65 | end 66 | 67 | local function setStyleProperty(id, property, value) 68 | if not id then 69 | return 70 | end 71 | 72 | local menu = menus[id] 73 | 74 | if menu then 75 | if not menu.overrideStyle then 76 | menu.overrideStyle = { } 77 | end 78 | 79 | menu.overrideStyle[property] = value 80 | end 81 | end 82 | 83 | local function getStyleProperty(property, menu) 84 | menu = menu or currentMenu 85 | 86 | if menu.overrideStyle then 87 | local value = menu.overrideStyle[property] 88 | if value then 89 | return value 90 | end 91 | end 92 | 93 | return menu.style and menu.style[property] or defaultStyle[property] 94 | end 95 | 96 | local function copyTable(t) 97 | if type(t) ~= 'table' then 98 | return t 99 | end 100 | 101 | local result = { } 102 | for k, v in pairs(t) do 103 | result[k] = copyTable(v) 104 | end 105 | 106 | return result 107 | end 108 | 109 | local function setMenuVisible(id, visible, holdCurrentOption) 110 | if currentMenu then 111 | if visible then 112 | if currentMenu.id == id then 113 | return 114 | end 115 | else 116 | if currentMenu.id ~= id then 117 | return 118 | end 119 | end 120 | end 121 | 122 | if visible then 123 | local menu = menus[id] 124 | 125 | if not currentMenu then 126 | menu.currentOption = 1 127 | else 128 | if not holdCurrentOption then 129 | menus[currentMenu.id].currentOption = 1 130 | end 131 | end 132 | 133 | currentMenu = menu 134 | else 135 | currentMenu = nil 136 | end 137 | end 138 | 139 | local function setTextParams(font, color, scale, center, shadow, alignRight, wrapFrom, wrapTo) 140 | SetTextFont(font) 141 | SetTextColour(color[1], color[2], color[3], color[4] or 255) 142 | SetTextScale(scale, scale) 143 | 144 | if shadow then 145 | SetTextDropShadow() 146 | end 147 | 148 | if center then 149 | SetTextCentre(true) 150 | elseif alignRight then 151 | SetTextRightJustify(true) 152 | end 153 | 154 | if not wrapFrom or not wrapTo then 155 | wrapFrom = wrapFrom or getStyleProperty('x') 156 | wrapTo = wrapTo or getStyleProperty('x') + getStyleProperty('width') - buttonTextXOffset 157 | end 158 | 159 | SetTextWrap(wrapFrom, wrapTo) 160 | end 161 | 162 | local function getLinesCount(text, x, y) 163 | BeginTextCommandLineCount('TWOSTRINGS') 164 | AddTextComponentString(tostring(text)) 165 | return EndTextCommandGetLineCount(x, y) 166 | end 167 | 168 | local function drawText(text, x, y) 169 | BeginTextCommandDisplayText('TWOSTRINGS') 170 | AddTextComponentString(tostring(text)) 171 | EndTextCommandDisplayText(x, y) 172 | end 173 | 174 | local function drawRect(x, y, width, height, color) 175 | DrawRect(x, y, width, height, color[1], color[2], color[3], color[4] or 255) 176 | end 177 | 178 | local function getCurrentIndex() 179 | if currentMenu.currentOption <= getStyleProperty('maxOptionCountOnScreen') and optionCount <= getStyleProperty('maxOptionCountOnScreen') then 180 | return optionCount 181 | elseif optionCount > currentMenu.currentOption - getStyleProperty('maxOptionCountOnScreen') and optionCount <= currentMenu.currentOption then 182 | return optionCount - (currentMenu.currentOption - getStyleProperty('maxOptionCountOnScreen')) 183 | end 184 | 185 | return nil 186 | end 187 | 188 | local function drawTitle() 189 | local x = getStyleProperty('x') + getStyleProperty('width') / 2 190 | local y = getStyleProperty('y') + titleHeight / 2 191 | 192 | if getStyleProperty('titleBackgroundSprite') then 193 | DrawSprite(getStyleProperty('titleBackgroundSprite').dict, getStyleProperty('titleBackgroundSprite').name, x, y, getStyleProperty('width'), titleHeight, 0., 255, 255, 255, 255) 194 | else 195 | drawRect(x, y, getStyleProperty('width'), titleHeight, getStyleProperty('titleBackgroundColor')) 196 | end 197 | 198 | if currentMenu.title then 199 | setTextParams(titleFont, getStyleProperty('titleColor'), titleScale, true) 200 | drawText(currentMenu.title, x, y - titleHeight / 2 + titleYOffset) 201 | end 202 | end 203 | 204 | local function drawSubTitle() 205 | local x = getStyleProperty('x') + getStyleProperty('width') / 2 206 | local y = getStyleProperty('y') + titleHeight + buttonHeight / 2 207 | 208 | drawRect(x, y, getStyleProperty('width'), buttonHeight, getStyleProperty('subTitleBackgroundColor')) 209 | 210 | setTextParams(buttonFont, getStyleProperty('subTitleColor'), buttonScale, false) 211 | drawText(currentMenu.subTitle, getStyleProperty('x') + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset) 212 | 213 | if optionCount > getStyleProperty('maxOptionCountOnScreen') then 214 | setTextParams(buttonFont, getStyleProperty('subTitleColor'), buttonScale, false, false, true) 215 | drawText(tostring(currentMenu.currentOption)..' / '..tostring(optionCount), getStyleProperty('x') + getStyleProperty('width'), y - buttonHeight / 2 + buttonTextYOffset) 216 | end 217 | end 218 | 219 | local function drawButton(text, subText) 220 | local currentIndex = getCurrentIndex() 221 | if not currentIndex then 222 | return 223 | end 224 | 225 | local backgroundColor = nil 226 | local textColor = nil 227 | local subTextColor = nil 228 | local shadow = false 229 | 230 | if currentMenu.currentOption == optionCount then 231 | backgroundColor = getStyleProperty('focusColor') 232 | textColor = getStyleProperty('focusTextColor') 233 | subTextColor = getStyleProperty('focusTextColor') 234 | else 235 | backgroundColor = getStyleProperty('backgroundColor') 236 | textColor = getStyleProperty('textColor') 237 | subTextColor = getStyleProperty('subTextColor') 238 | shadow = true 239 | end 240 | 241 | local x = getStyleProperty('x') + getStyleProperty('width') / 2 242 | local y = getStyleProperty('y') + titleHeight + buttonHeight + (buttonHeight * currentIndex) - buttonHeight / 2 243 | 244 | drawRect(x, y, getStyleProperty('width'), buttonHeight, backgroundColor) 245 | 246 | setTextParams(buttonFont, textColor, buttonScale, false, shadow) 247 | drawText(text, getStyleProperty('x') + buttonTextXOffset, y - (buttonHeight / 2) + buttonTextYOffset) 248 | 249 | if subText then 250 | setTextParams(buttonFont, subTextColor, buttonScale, false, shadow, true) 251 | drawText(subText, getStyleProperty('x') + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset) 252 | end 253 | end 254 | 255 | function WarMenu.CreateMenu(id, title, subTitle, style) 256 | -- Default settings 257 | local menu = { } 258 | 259 | -- Members 260 | menu.id = id 261 | menu.previousMenu = nil 262 | menu.aboutToBeClosed = false 263 | menu.currentOption = 1 264 | menu.title = title 265 | menu.subTitle = subTitle and string.upper(subTitle) or 'INTERACTION MENU' 266 | 267 | -- Style 268 | if style then 269 | menu.style = style 270 | end 271 | 272 | menus[id] = menu 273 | end 274 | 275 | function WarMenu.CreateSubMenu(id, parent, subTitle, style) 276 | local parentMenu = menus[parent] 277 | if not parentMenu then 278 | return 279 | end 280 | 281 | WarMenu.CreateMenu(id, parentMenu.title, subTitle and string.upper(subTitle) or parentMenu.subTitle) 282 | 283 | local menu = menus[id] 284 | 285 | menu.previousMenu = parent 286 | 287 | if parentMenu.overrideStyle then 288 | menu.overrideStyle = copyTable(parentMenu.overrideStyle) 289 | end 290 | 291 | if style then 292 | menu.style = style 293 | elseif parentMenu.style then 294 | menu.style = copyTable(parentMenu.style) 295 | end 296 | end 297 | 298 | function WarMenu.CurrentMenu() 299 | return currentMenu and currentMenu.id or nil 300 | end 301 | 302 | function WarMenu.OpenMenu(id) 303 | if id and menus[id] then 304 | PlaySoundFrontend(-1, 'SELECT', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 305 | setMenuVisible(id, true) 306 | end 307 | end 308 | 309 | function WarMenu.IsMenuOpened(id) 310 | return currentMenu and currentMenu.id == id 311 | end 312 | WarMenu.Begin = WarMenu.IsMenuOpened 313 | 314 | function WarMenu.IsAnyMenuOpened() 315 | return currentMenu ~= nil 316 | end 317 | 318 | function WarMenu.IsMenuAboutToBeClosed() 319 | return currentMenu and currentMenu.aboutToBeClosed 320 | end 321 | 322 | function WarMenu.CloseMenu() 323 | if not currentMenu then 324 | return 325 | end 326 | 327 | if currentMenu.aboutToBeClosed then 328 | currentMenu.aboutToBeClosed = false 329 | setMenuVisible(currentMenu.id, false) 330 | optionCount = 0 331 | currentKey = nil 332 | PlaySoundFrontend(-1, 'QUIT', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 333 | else 334 | currentMenu.aboutToBeClosed = true 335 | end 336 | end 337 | 338 | function WarMenu.ToolTip(text, width, flipHorizontal) 339 | if not currentMenu then 340 | return 341 | end 342 | 343 | local currentIndex = getCurrentIndex() 344 | if not currentIndex then 345 | return 346 | end 347 | 348 | width = width or toolTipWidth 349 | 350 | local x = nil 351 | if not flipHorizontal then 352 | x = getStyleProperty('x') + getStyleProperty('width') + width / 2 + buttonTextXOffset 353 | else 354 | x = getStyleProperty('x') - width / 2 - buttonTextXOffset 355 | end 356 | 357 | local textX = x - (width / 2) + buttonTextXOffset 358 | setTextParams(buttonFont, getStyleProperty('textColor'), buttonScale, false, true, false, textX, textX + width - (buttonTextYOffset * 2)) 359 | local linesCount = getLinesCount(text, textX, getStyleProperty('y')) 360 | 361 | local height = GetTextScaleHeight(buttonScale, buttonFont) * (linesCount + 1) + buttonTextYOffset 362 | local y = getStyleProperty('y') + titleHeight + (buttonHeight * currentIndex) + height / 2 363 | 364 | drawRect(x, y, width, height, getStyleProperty('backgroundColor')) 365 | 366 | y = y - (height / 2) + buttonTextYOffset 367 | drawText(text, textX, y) 368 | end 369 | 370 | function WarMenu.Button(text, subText) 371 | if not currentMenu then 372 | return 373 | end 374 | 375 | optionCount = optionCount + 1 376 | 377 | drawButton(text, subText) 378 | 379 | local pressed = false 380 | 381 | if currentMenu.currentOption == optionCount then 382 | if currentKey == keys.select then 383 | pressed = true 384 | PlaySoundFrontend(-1, getStyleProperty('buttonPressedSound').name, getStyleProperty('buttonPressedSound').set, true) 385 | elseif currentKey == keys.left or currentKey == keys.right then 386 | PlaySoundFrontend(-1, 'NAV_UP_DOWN', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 387 | end 388 | end 389 | 390 | return pressed 391 | end 392 | 393 | function WarMenu.SpriteButton(text, dict, name, r, g, b, a) 394 | if not currentMenu then 395 | return 396 | end 397 | 398 | local pressed = WarMenu.Button(text) 399 | 400 | local currentIndex = getCurrentIndex() 401 | if not currentIndex then 402 | return 403 | end 404 | 405 | if not HasStreamedTextureDictLoaded(dict) then 406 | RequestStreamedTextureDict(dict) 407 | end 408 | DrawSprite(dict, name, getStyleProperty('x') + getStyleProperty('width') - spriteWidth / 2 - buttonSpriteXOffset, getStyleProperty('y') + titleHeight + buttonHeight + (buttonHeight * currentIndex) - spriteHeight / 2 + buttonSpriteYOffset, spriteWidth, spriteHeight, 0., r or 255, g or 255, b or 255, a or 255) 409 | 410 | return pressed 411 | end 412 | 413 | function WarMenu.InputButton(text, windowTitleEntry, defaultText, maxLength, subText) 414 | if not currentMenu then 415 | return 416 | end 417 | 418 | local pressed = WarMenu.Button(text, subText) 419 | local inputText = nil 420 | 421 | if pressed then 422 | DisplayOnscreenKeyboard(1, windowTitleEntry or 'FMMC_MPM_NA', '', defaultText or '', '', '', '', maxLength or 255) 423 | 424 | while true do 425 | DisableAllControlActions(0) 426 | 427 | local status = UpdateOnscreenKeyboard() 428 | if status == 2 then 429 | break 430 | elseif status == 1 then 431 | inputText = GetOnscreenKeyboardResult() 432 | break 433 | end 434 | 435 | Citizen.Wait(0) 436 | end 437 | end 438 | 439 | return pressed, inputText 440 | end 441 | 442 | function WarMenu.MenuButton(text, id, subText) 443 | if not currentMenu then 444 | return 445 | end 446 | 447 | local pressed = WarMenu.Button(text, subText) 448 | 449 | if pressed then 450 | currentMenu.currentOption = optionCount 451 | setMenuVisible(currentMenu.id, false) 452 | setMenuVisible(id, true, true) 453 | end 454 | 455 | return pressed 456 | end 457 | 458 | function WarMenu.CheckBox(text, checked, callback) 459 | if not currentMenu then 460 | return 461 | end 462 | 463 | local name = nil 464 | if currentMenu.currentOption == optionCount + 1 then 465 | name = checked and 'shop_box_tickb' or 'shop_box_blankb' 466 | else 467 | name = checked and 'shop_box_tick' or 'shop_box_blank' 468 | end 469 | 470 | local pressed = WarMenu.SpriteButton(text, 'commonmenu', name) 471 | 472 | if pressed then 473 | checked = not checked 474 | if callback then callback(checked) end 475 | end 476 | 477 | return pressed 478 | end 479 | 480 | function WarMenu.ComboBox(text, items, currentIndex, selectedIndex, callback) 481 | if not currentMenu then 482 | return 483 | end 484 | 485 | local itemsCount = #items 486 | local selectedItem = items[currentIndex] 487 | local isCurrent = currentMenu.currentOption == optionCount + 1 488 | selectedIndex = selectedIndex or currentIndex 489 | 490 | 491 | if itemsCount > 1 and isCurrent then 492 | 493 | if GetLabelText(selectedItem) ~= 'NULL' then 494 | selectedItem = '← '..tostring(GetLabelText(selectedItem))..' →' 495 | else 496 | selectedItem = '← '..tostring(selectedItem)..' →' 497 | end 498 | elseif itemsCount > 1 and not isCurrent then 499 | if GetLabelText(selectedItem) ~= 'NULL' then 500 | selectedItem = tostring(GetLabelText(selectedItem)) 501 | else 502 | selectedItem = tostring(selectedItem) 503 | end 504 | end 505 | 506 | local pressed = WarMenu.Button(text, selectedItem) 507 | 508 | if pressed then 509 | selectedIndex = currentIndex 510 | elseif isCurrent then 511 | if currentKey == keys.left then 512 | if currentIndex > 1 then currentIndex = currentIndex - 1 else currentIndex = itemsCount end 513 | elseif currentKey == keys.right then 514 | if currentIndex < itemsCount then currentIndex = currentIndex + 1 else currentIndex = 1 end 515 | end 516 | end 517 | 518 | if callback then callback(currentIndex, selectedIndex) end 519 | return pressed, currentIndex 520 | end 521 | 522 | function WarMenu.Display() 523 | if currentMenu then 524 | DisableControlAction(0, keys.left, true) 525 | DisableControlAction(0, keys.up, true) 526 | DisableControlAction(0, keys.down, true) 527 | DisableControlAction(0, keys.right, true) 528 | DisableControlAction(0, keys.back, true) 529 | 530 | if currentMenu.aboutToBeClosed then 531 | WarMenu.CloseMenu() 532 | else 533 | ClearAllHelpMessages() 534 | 535 | drawTitle() 536 | drawSubTitle() 537 | 538 | currentKey = nil 539 | 540 | if IsDisabledControlJustReleased(0, keys.down) then 541 | PlaySoundFrontend(-1, 'NAV_UP_DOWN', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 542 | 543 | if currentMenu.currentOption < optionCount then 544 | currentMenu.currentOption = currentMenu.currentOption + 1 545 | else 546 | currentMenu.currentOption = 1 547 | end 548 | elseif IsDisabledControlJustReleased(0, keys.up) then 549 | PlaySoundFrontend(-1, 'NAV_UP_DOWN', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 550 | 551 | if currentMenu.currentOption > 1 then 552 | currentMenu.currentOption = currentMenu.currentOption - 1 553 | else 554 | currentMenu.currentOption = optionCount 555 | end 556 | elseif IsDisabledControlJustReleased(0, keys.left) then 557 | currentKey = keys.left 558 | elseif IsDisabledControlJustReleased(0, keys.right) then 559 | currentKey = keys.right 560 | elseif IsControlJustReleased(0, keys.select) then 561 | currentKey = keys.select 562 | elseif IsDisabledControlJustReleased(0, keys.back) then 563 | if menus[currentMenu.previousMenu] then 564 | setMenuVisible(currentMenu.previousMenu, true) 565 | PlaySoundFrontend(-1, 'BACK', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true) 566 | else 567 | WarMenu.CloseMenu() 568 | end 569 | end 570 | 571 | optionCount = 0 572 | end 573 | end 574 | end 575 | WarMenu.End = WarMenu.Display 576 | 577 | function WarMenu.CurrentOption() 578 | if currentMenu and optionCount ~= 0 then 579 | return currentMenu.currentOption 580 | end 581 | 582 | return nil 583 | end 584 | 585 | function WarMenu.IsItemHovered() 586 | if not currentMenu or optionCount == 0 then 587 | return false 588 | end 589 | 590 | return currentMenu.currentOption == optionCount 591 | end 592 | 593 | function WarMenu.IsItemSelected() 594 | return currentKey == keys.select and WarMenu.IsItemHovered() 595 | end 596 | 597 | function WarMenu.SetTitle(id, title) 598 | setMenuProperty(id, 'title', title) 599 | end 600 | WarMenu.SetMenuTitle = WarMenu.SetTitle 601 | 602 | function WarMenu.SetSubTitle(id, text) 603 | setMenuProperty(id, 'subTitle', string.upper(text)) 604 | end 605 | WarMenu.SetMenuSubTitle = WarMenu.SetSubTitle 606 | 607 | function WarMenu.SetMenuStyle(id, style) 608 | setMenuProperty(id, 'style', style) 609 | end 610 | 611 | function WarMenu.SetMenuX(id, x) 612 | setStyleProperty(id, 'x', x) 613 | end 614 | 615 | function WarMenu.SetMenuY(id, y) 616 | setStyleProperty(id, 'y', y) 617 | end 618 | 619 | function WarMenu.SetMenuWidth(id, width) 620 | setStyleProperty(id, 'width', width) 621 | end 622 | 623 | function WarMenu.SetMenuMaxOptionCountOnScreen(id, count) 624 | setStyleProperty(id, 'maxOptionCountOnScreen', count) 625 | end 626 | 627 | function WarMenu.SetTitleColor(id, r, g, b, a) 628 | setStyleProperty(id, 'titleColor', { r, g, b, a }) 629 | end 630 | WarMenu.SetMenuTitleColor = WarMenu.SetTitleColor 631 | 632 | function WarMenu.SetMenuSubTitleColor(id, r, g, b, a) 633 | setStyleProperty(id, 'subTitleColor', { r, g, b, a }) 634 | end 635 | 636 | function WarMenu.SetTitleBackgroundColor(id, r, g, b, a) 637 | setStyleProperty(id, 'titleBackgroundColor', { r, g, b, a }) 638 | end 639 | WarMenu.SetMenuTitleBackgroundColor = WarMenu.SetTitleBackgroundColor 640 | 641 | function WarMenu.SetTitleBackgroundSprite(id, dict, name) 642 | RequestStreamedTextureDict(dict) 643 | setStyleProperty(id, 'titleBackgroundSprite', { dict = dict, name = name }) 644 | end 645 | WarMenu.SetMenuTitleBackgroundSprite = WarMenu.SetTitleBackgroundSprite 646 | 647 | function WarMenu.SetMenuBackgroundColor(id, r, g, b, a) 648 | setStyleProperty(id, 'backgroundColor', { r, g, b, a }) 649 | end 650 | 651 | function WarMenu.SetMenuTextColor(id, r, g, b, a) 652 | setStyleProperty(id, 'textColor', { r, g, b, a }) 653 | end 654 | 655 | function WarMenu.SetMenuSubTextColor(id, r, g, b, a) 656 | setStyleProperty(id, 'subTextColor', { r, g, b, a }) 657 | end 658 | 659 | function WarMenu.SetMenuFocusColor(id, r, g, b, a) 660 | setStyleProperty(id, 'focusColor', { r, g, b, a }) 661 | end 662 | 663 | function WarMenu.SetMenuFocusTextColor(id, r, g, b, a) 664 | setStyleProperty(id, 'focusTextColor', { r, g, b, a }) 665 | end 666 | 667 | function WarMenu.SetMenuButtonPressedSound(id, name, set) 668 | setStyleProperty(id, 'buttonPressedSound', { name = name, set = set }) 669 | end 670 | --------------------------------------------------------------------------------