├── 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 |

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 | [](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 |
--------------------------------------------------------------------------------