├── LICENSE ├── README.md ├── client ├── bridge │ ├── custom.lua │ ├── esx.lua │ ├── ox.lua │ └── qb.lua ├── client.lua ├── functions │ ├── menu.lua │ ├── payment.lua │ └── utils.lua └── vehicle │ ├── colorList.lua │ ├── modList.lua │ └── vehicles.lua ├── config.lua ├── fxmanifest.lua ├── locales ├── cs.json ├── en.json └── it.json └── server ├── bridge ├── custom.lua ├── esx.lua ├── ox.lua └── qb.lua └── server.lua /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 🛠️ Ars Tuning 3 | 4 | 5 | 6 | **Frameworks supported:** 7 | > *esx* 8 | > 9 | > *qb-core* 10 | > 11 | > *ox_core* 12 | 13 | **Dependencies:** 14 | > *ox_lib* 15 | 16 | **Features** 17 | > *Dynamic menu icons color change (the icons of the* 18 | > *menu changes based on your vehicle color)* 19 | > 20 | > *Statistics menu (color changes based on your vehicle color)* 21 | > 22 | > *Option to add blip on the map* 23 | > 24 | > *Option to make the tuning restricted to certain job* 25 | > 26 | 27 | **To do in the future** 28 | > *Camera movement* 29 | > 30 | > *Payment system (hard with context menu)* 31 | 32 | Preview 33 | https://www.youtube.com/watch?v=FNEg1aXmd-0&feature=youtu.be&ab_channel=AriusDevelopment 34 | -------------------------------------------------------------------------------- /client/bridge/custom.lua: -------------------------------------------------------------------------------- 1 | -- function hasAccess(job) 2 | -- if not job then return true end 3 | 4 | -- --- add 5 | 6 | -- return false 7 | -- end -------------------------------------------------------------------------------- /client/bridge/esx.lua: -------------------------------------------------------------------------------- 1 | local esx = GetResourceState('es_extended'):find('start') 2 | if not esx then return end 3 | 4 | local ESX = exports.es_extended:getSharedObject() 5 | 6 | function hasAccess(job) 7 | if not job then return true end 8 | 9 | local playerData = ESX.GetPlayerData() 10 | 11 | if playerData.job.name == job then return true end 12 | 13 | return false 14 | end -------------------------------------------------------------------------------- /client/bridge/ox.lua: -------------------------------------------------------------------------------- 1 | local ox = GetResourceState('ox_core'):find("start") 2 | if not ox then return end 3 | 4 | 5 | local file = ('imports/%s.lua'):format(IsDuplicityVersion() and 'server' or 'client') 6 | local import = LoadResourceFile('ox_core', file) 7 | local chunk = assert(load(import, ('@@ox_core/%s'):format(file))) 8 | 9 | chunk() 10 | 11 | function hasAccess(job) 12 | if not job then return true end 13 | 14 | for k,v in pairs(player.groups) do 15 | if k == job then return true end 16 | end 17 | 18 | return false 19 | end -------------------------------------------------------------------------------- /client/bridge/qb.lua: -------------------------------------------------------------------------------- 1 | local qb = GetResourceState('qb-core'):find("start") 2 | if not qb then return end 3 | 4 | local QBCore = exports['qb-core']:GetCoreObject() 5 | 6 | function hasAccess(job) 7 | if not job then return true end 8 | 9 | local playerData = QBCore.Functions.GetPlayerData() 10 | 11 | if playerData.job.name == job then return true end 12 | 13 | return false 14 | end -------------------------------------------------------------------------------- /client/client.lua: -------------------------------------------------------------------------------- 1 | local Config = require "config" 2 | 3 | 4 | local points = {} 5 | points.workshops = {} 6 | 7 | for i = 1, #Config.WorkShops do 8 | local cfg = Config.WorkShops[i] 9 | 10 | if cfg.blip.enable then 11 | local blip = AddBlipForCoord(cfg.pos) 12 | 13 | SetBlipSprite(blip, cfg.blip.type) 14 | SetBlipDisplay(blip, 6) 15 | SetBlipScale(blip, cfg.blip.scale) 16 | SetBlipColour(blip, cfg.blip.color) 17 | SetBlipAsShortRange(blip, true) 18 | 19 | BeginTextCommandSetBlipName('STRING') 20 | AddTextComponentString(cfg.blip.name) 21 | EndTextCommandSetBlipName(blip) 22 | end 23 | 24 | points.workshops[i] = lib.points.new({ 25 | coords = cfg.pos, 26 | distance = 8, 27 | onEnter = function(self) 28 | if cache.vehicle and hasAccess(cfg.job) then 29 | lib.showTextUI("[E] - open workshop") 30 | end 31 | end, 32 | onExit = function(self) 33 | lib.hideTextUI() 34 | end, 35 | nearby = function(self) 36 | if cache.vehicle and hasAccess(cfg.job) then 37 | DrawMarker(0, self.coords.x, self.coords.y, self.coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.8, 0.8, 38 | 199, 208, 209, 100, false, true, 2, nil, nil, false) 39 | if self.currentDistance < 1 and IsControlJustReleased(0, 38) then 40 | local vehicle = cache.vehicle 41 | currentVehProperties.old = getVehicleProperties(vehicle) 42 | 43 | local color1_r, color1_g, color1_b = GetVehicleCustomPrimaryColour(vehicle) 44 | currentVehProperties.old.color1 = { color1_r, color1_g, color1_b } 45 | 46 | local color2_r, color2_g, color2_b = GetVehicleCustomSecondaryColour(vehicle) 47 | currentVehProperties.old.color2 = { color2_r, color2_g, color2_b } 48 | 49 | openTuningMenu() 50 | end 51 | end 52 | end 53 | }) 54 | end 55 | -------------------------------------------------------------------------------- /client/functions/menu.lua: -------------------------------------------------------------------------------- 1 | local mods = require "client.vehicle.modList" 2 | local colors = require "client.vehicle.colorList" 3 | 4 | currentVehProperties = {} 5 | cart = {} 6 | 7 | lib.locale() 8 | 9 | local function openModsMenu(veh, mod, maxMods) 10 | if maxMods < 1 then return lib.showTextUI('No mods') end 11 | local options = {} 12 | 13 | local vehicle = veh 14 | local modType = nil 15 | local modTitle = nil 16 | 17 | for k, v in pairs(mods) do 18 | if v.modNum == mod then 19 | modTitle = v.title 20 | modType = k 21 | modNum = v.modNum 22 | modLabel = v.label 23 | parentMenu = v.parent 24 | modPrice = v.price 25 | 26 | if modNum == 23 then modType = "modFrontWheels" end 27 | 28 | icon = v.icon or "car" 29 | 30 | currentMod = getVehicleProperties(vehicle)[modType] 31 | 32 | break 33 | end 34 | Wait(1) 35 | end 36 | 37 | local vehiclePrice = getVehiclePrice(vehicle) or 100 38 | SetVehicleModKit(veh, 0) 39 | 40 | for i = 0, maxMods, 1 do 41 | local modNumToSet = i - 1 42 | 43 | local modNativeLabel = GetLabelText(GetModTextLabel(vehicle, modNum, modNumToSet)) 44 | 45 | if modNativeLabel == "NULL" then 46 | modLabel = modLabel 47 | else 48 | modLabel = modNativeLabel 49 | end 50 | 51 | if modNumToSet == -1 then 52 | menuTitle = locale("base_mod") 53 | else 54 | menuTitle = modLabel .. " " .. i 55 | end 56 | 57 | if modType == "modHorns" then menuTitle = getHornName(i) end 58 | 59 | if modNumToSet == currentMod or modNumToSet == maxMods then 60 | disabled = true 61 | else 62 | disabled = false 63 | end 64 | 65 | local modPercentage 66 | if type(modPrice) == "table" then 67 | for m = 1, #modPrice, 1 do 68 | if i == m then 69 | modPercentage = modPrice[i] / 100 70 | break 71 | elseif modNumToSet == -1 then 72 | modPercentage = modPrice[1] / 100 73 | break 74 | end 75 | end 76 | else 77 | modPercentage = modPrice / 100 78 | end 79 | 80 | local price = vehiclePrice * modPercentage 81 | 82 | table.insert(options, 83 | { 84 | title = menuTitle, 85 | icon = icon, 86 | iconColor = getVehicleColor(), 87 | disabled = disabled, 88 | description = price .. "€", 89 | onSelect = function() 90 | local properties = {} 91 | properties[modType] = modNumToSet 92 | lib.setVehicleProperties(vehicle, properties) 93 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 94 | 95 | local mods = getVehicleModCounts(vehicle, modNum) 96 | 97 | openModsMenu(vehicle, modNum, mods) 98 | 99 | local newModData = { 100 | modLabel = modLabel, 101 | modType = modType, 102 | modNum = modNum, 103 | modLevel = modNumToSet, 104 | modPrice = price, 105 | } 106 | 107 | local foundMatch = false 108 | for l, existingModData in ipairs(cart) do 109 | if existingModData.modType == modType then 110 | cart[l] = newModData 111 | foundMatch = true 112 | break 113 | end 114 | end 115 | 116 | if not foundMatch then 117 | table.insert(cart, newModData) 118 | end 119 | currentVehProperties.new = getVehicleProperties(vehicle) 120 | end 121 | } 122 | ) 123 | Wait(1) 124 | end 125 | 126 | lib.registerContext({ 127 | id = 'modsMenu' .. mod, 128 | menu = parentMenu, 129 | title = modTitle, 130 | options = options, 131 | onExit = onExit, 132 | }) 133 | 134 | lib.showContext('modsMenu' .. mod) 135 | end 136 | 137 | 138 | local function openTurboMenu() 139 | local vehicle = cache.vehicle 140 | local enabled = getVehicleProperties(vehicle).modTurbo 141 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 142 | 143 | 144 | lib.registerContext({ 145 | id = 'turboMenu', 146 | menu = mods.modTurbo.parent, 147 | title = mods.modTurbo.title, 148 | onExit = onExit, 149 | options = { 150 | { 151 | title = locale("turbo_enabled"), 152 | icon = mods.modTurbo.icon, 153 | iconColor = getVehicleColor(), 154 | disabled = enabled, 155 | onSelect = function() 156 | lib.setVehicleProperties(vehicle, { modTurbo = true }) 157 | 158 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 159 | openTurboMenu() 160 | 161 | local modPercentage = mods.modTurbo.price / 100 162 | 163 | local price = vehiclePrice * modPercentage 164 | 165 | local newModData = { 166 | modLabel = locale("turbo_title"), 167 | modType = "modTurbo", 168 | modLevel = locale("turbo_enabled"), 169 | modPrice = price 170 | } 171 | 172 | local foundMatch = false 173 | for i, existingModData in ipairs(cart) do 174 | if existingModData.modType == "modTurbo" then 175 | cart[i] = newModData 176 | foundMatch = true 177 | break 178 | end 179 | end 180 | 181 | if not foundMatch then 182 | table.insert(cart, newModData) 183 | end 184 | currentVehProperties.new = getVehicleProperties(vehicle) 185 | end 186 | }, 187 | { 188 | title = locale("turbo_disabled"), 189 | icon = mods.modTurbo.icon, 190 | iconColor = getVehicleColor(), 191 | disabled = not enabled, 192 | onSelect = function() 193 | lib.setVehicleProperties(vehicle, { modTurbo = false }) 194 | 195 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 196 | openTurboMenu() 197 | 198 | local modPercentage = mods.modTurbo.price / 100 199 | 200 | local price = vehiclePrice * modPercentage 201 | 202 | local newModData = { 203 | modLabel = locale("turbo_title"), 204 | modType = "modTurbo", 205 | modLevel = locale("turbo_disabled"), 206 | modPrice = price, 207 | } 208 | 209 | local foundMatch = false 210 | for i, existingModData in ipairs(cart) do 211 | if existingModData.modType == "modTurbo" then 212 | cart[i] = newModData 213 | foundMatch = true 214 | break 215 | end 216 | end 217 | 218 | if not foundMatch then 219 | table.insert(cart, newModData) 220 | end 221 | currentVehProperties.new = getVehicleProperties(vehicle) 222 | end 223 | }, 224 | } 225 | }) 226 | 227 | lib.showContext('turboMenu') 228 | end 229 | 230 | local function openUpgradeMenu() 231 | lib.registerContext({ 232 | id = 'upgradeMenu', 233 | title = locale("upgrade_category_title"), 234 | menu = "tuningMenu", 235 | onExit = onExit, 236 | options = { 237 | { 238 | title = locale("engine_title"), 239 | icon = mods.modEngine.icon or "gear", 240 | iconColor = getVehicleColor(), 241 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modEngine.modNum) > 0), 242 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modEngine.modNum)), 243 | onSelect = function() 244 | local vehicle = cache.vehicle 245 | 246 | local mod = mods.modEngine.modNum 247 | local mods = getVehicleModCounts(vehicle, mod) 248 | 249 | openModsMenu(vehicle, mod, mods) 250 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 251 | end, 252 | }, 253 | { 254 | title = locale("brakes_title"), 255 | icon = mods.modBrakes.icon or 'b', 256 | iconColor = getVehicleColor(), 257 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modBrakes.modNum) > 0), 258 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modBrakes.modNum)), 259 | onSelect = function() 260 | local vehicle = cache.vehicle 261 | 262 | local mod = mods.modBrakes.modNum 263 | local mods = getVehicleModCounts(vehicle, mod) 264 | 265 | openModsMenu(vehicle, mod, mods) 266 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 267 | end, 268 | }, 269 | { 270 | title = locale("transmission_title"), 271 | icon = mods.modTransmission.icon or 'gear', 272 | iconColor = getVehicleColor(), 273 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modTransmission.modNum) > 0), 274 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modTransmission.modNum)), 275 | onSelect = function() 276 | local vehicle = cache.vehicle 277 | 278 | local mod = mods.modTransmission.modNum 279 | local mods = getVehicleModCounts(vehicle, mod) 280 | 281 | openModsMenu(vehicle, mod, mods) 282 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 283 | end, 284 | }, 285 | { 286 | title = locale("suspension_title"), 287 | icon = mods.modSuspension.icon or 'wrench', 288 | iconColor = getVehicleColor(), 289 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSuspension.modNum) > 0), 290 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSuspension.modNum)), 291 | onSelect = function() 292 | local vehicle = cache.vehicle 293 | 294 | local mod = mods.modSuspension.modNum 295 | local mods = getVehicleModCounts(vehicle, mod) 296 | 297 | openModsMenu(vehicle, mod, mods) 298 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 299 | end, 300 | }, 301 | { 302 | title = locale("armor_title"), 303 | icon = mods.modArmor.icon or 'shield', 304 | iconColor = getVehicleColor(), 305 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modArmor.modNum) > 0), 306 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modArmor.modNum)), 307 | onSelect = function() 308 | local vehicle = cache.vehicle 309 | 310 | local mod = mods.modArmor.modNum 311 | local mods = getVehicleModCounts(vehicle, mod) 312 | 313 | openModsMenu(vehicle, mod, mods) 314 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 315 | end, 316 | }, 317 | { 318 | title = locale("turbo_title"), 319 | icon = mods.modTurbo.icon or 'gauge-high', 320 | iconColor = getVehicleColor(), 321 | description = "1", 322 | onSelect = function() 323 | openTurboMenu() 324 | end, 325 | }, 326 | } 327 | }) 328 | 329 | lib.showContext('upgradeMenu') 330 | end 331 | 332 | -- RegisterCommand("prop", function(source, args, raw) 333 | -- local ve = getVehicleProperties(cache.vehicle) 334 | -- print(json.encode(ve, { indent = true })) 335 | -- print(ve.modEngine) 336 | -- end) 337 | 338 | local function openPearlescentMenu() 339 | local options = {} 340 | local vehicle = cache.vehicle 341 | local colors = colors.pearlescent 342 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 343 | 344 | for i = 1, #colors, 1 do 345 | table.insert(options, 346 | { 347 | title = colors[i].category, 348 | icon = 'paint-roller', 349 | iconColor = colors[i].color, 350 | onSelect = function() 351 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 352 | local options = {} 353 | 354 | 355 | local modPercentage = mods.color.price / 100 356 | 357 | local price = vehiclePrice * modPercentage 358 | 359 | for j = 1, #colors[i].colors do 360 | local disabled = false 361 | 362 | if getVehicleProperties(vehicle).pearlescentColor == colors[i].colors[j].index then 363 | disabled = true 364 | end 365 | 366 | table.insert(options, 367 | { 368 | title = colors[i].colors[j].label, 369 | icon = mods.color.icon, 370 | iconColor = colors[i].colors[j].iconColor, 371 | disabled = disabled, 372 | description = price .. "$", 373 | onSelect = function() 374 | lib.setVehicleProperties(vehicle, { pearlescentColor = colors[i].colors[j].index }) 375 | 376 | local newModData = { 377 | modLabel = " ", 378 | modType = "pearlescentColor", 379 | modLevel = colors[i].colors[j].label, 380 | modPrice = price, 381 | } 382 | 383 | local foundMatch = false 384 | for i, existingModData in ipairs(cart) do 385 | if existingModData.modType == "pearlescentColor" then 386 | cart[i] = newModData 387 | foundMatch = true 388 | break 389 | end 390 | end 391 | 392 | if not foundMatch then 393 | table.insert(cart, newModData) 394 | end 395 | currentVehProperties.new = getVehicleProperties(vehicle) 396 | 397 | openPearlescentMenu() 398 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 399 | end 400 | 401 | } 402 | ) 403 | end 404 | 405 | lib.registerContext({ 406 | id = colors[i].category, 407 | title = colors[i].category, 408 | menu = "pearlescentColor", 409 | onExit = function() 410 | lib.hideTextUI() 411 | confirmPayment() 412 | end, 413 | options = options 414 | }) 415 | 416 | lib.showContext(colors[i].category) 417 | end, 418 | } 419 | ) 420 | end 421 | 422 | lib.registerContext({ 423 | id = 'pearlescentColor', 424 | title = locale("pearlescent_color_title"), 425 | menu = "colorMenu", 426 | onExit = onExit, 427 | options = options 428 | }) 429 | 430 | lib.showContext('pearlescentColor') 431 | end 432 | 433 | local function openXenonMenu() 434 | local options = {} 435 | 436 | local vehicle = cache.vehicle 437 | local colors = colors.xenon 438 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 439 | 440 | for i = 1, #colors, 1 do 441 | local disabled = false 442 | 443 | local currentXenon = getVehicleProperties(vehicle).xenonColor 444 | 445 | if currentXenon == 255 and getVehicleProperties(cache.vehicle).modXenon then currentXenon = -1 end 446 | 447 | if currentXenon == colors[i].index then 448 | disabled = true 449 | end 450 | 451 | local modPercentage = mods.modXenon.price / 100 452 | 453 | local price = vehiclePrice * modPercentage 454 | 455 | table.insert(options, 456 | { 457 | title = colors[i].label, 458 | icon = 'lightbulb', 459 | iconColor = colors[i].iconColor, 460 | disabled = disabled, 461 | description = price .. "$", 462 | onSelect = function() 463 | lib.setVehicleProperties(vehicle, { modXenon = true }) 464 | lib.setVehicleProperties(vehicle, { xenonColor = colors[i].index }) 465 | 466 | local newModData = { 467 | modLabel = locale("xenon_title"), 468 | modType = "modXenon", 469 | modLevel = colors[i].label, 470 | modPrice = price, 471 | } 472 | 473 | local foundMatch = false 474 | for i, existingModData in ipairs(cart) do 475 | if existingModData.modType == "modXenon" then 476 | cart[i] = newModData 477 | foundMatch = true 478 | break 479 | end 480 | end 481 | 482 | if not foundMatch then 483 | table.insert(cart, newModData) 484 | end 485 | currentVehProperties.new = getVehicleProperties(vehicle) 486 | 487 | openXenonMenu() 488 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 489 | end, 490 | } 491 | ) 492 | 493 | if i == #colors then 494 | table.insert(options, 495 | { 496 | title = locale("disable_xenon"), 497 | icon = 'lightbulb', 498 | iconColor = "#fff", 499 | description = price .. "$", 500 | disabled = not getVehicleProperties(cache.vehicle).modXenon, 501 | onSelect = function() 502 | lib.setVehicleProperties(vehicle, { modXenon = false }) 503 | lib.setVehicleProperties(vehicle, { xenonColor = -1 }) 504 | 505 | 506 | local newModData = { 507 | modLabel = locale("xenon_title"), 508 | modType = "modXenon", 509 | modLevel = colors[i].label, 510 | modPrice = price, 511 | } 512 | 513 | local foundMatch = false 514 | for i, existingModData in ipairs(cart) do 515 | if existingModData.modType == "modXenon" then 516 | cart[i] = newModData 517 | foundMatch = true 518 | break 519 | end 520 | end 521 | 522 | if not foundMatch then 523 | table.insert(cart, newModData) 524 | end 525 | currentVehProperties.new = getVehicleProperties(vehicle) 526 | 527 | 528 | openXenonMenu() 529 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 530 | end, 531 | } 532 | ) 533 | end 534 | end 535 | 536 | lib.registerContext({ 537 | id = 'xenonLights', 538 | title = locale("xenon_title"), 539 | menu = "cosmeticsMenu", 540 | onBack = function() 541 | end, 542 | onExit = onExit, 543 | options = options 544 | }) 545 | 546 | lib.showContext('xenonLights') 547 | end 548 | 549 | local function openColorMenu() 550 | local vehicle = cache.vehicle 551 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 552 | local modPercentage = mods.color.price / 100 553 | local price = vehiclePrice * modPercentage 554 | 555 | lib.registerContext({ 556 | id = 'colorMenu', 557 | title = locale("color_title"), 558 | menu = "cosmeticsMenu", 559 | onExit = onExit, 560 | options = { 561 | { 562 | title = locale("primary_color_title"), 563 | icon = mods.color.icon, 564 | iconColor = "rgba(132, 0, 247, 1.0)", 565 | description = price .. "$", 566 | onSelect = function() 567 | local input = lib.inputDialog(locale("select_color"), { 568 | { type = 'color', label = locale("color_input"), format = "rgb" }, 569 | { 570 | type = 'select', 571 | label = locale("color_type"), 572 | default = "0", 573 | clearable = true, 574 | options = { 575 | { value = "0", label = locale("color_type_normal") }, 576 | { value = "1", label = locale("color_type_metalic") }, 577 | { value = "2", label = locale("color_type_pearl") }, 578 | { value = "3", label = locale("color_type_matte") }, 579 | { value = "4", label = locale("color_type_metal") }, 580 | { value = "5", label = locale("color_type_chrome") }, 581 | } 582 | }, 583 | }) 584 | 585 | if not input then 586 | openColorMenu() 587 | return 588 | end 589 | 590 | local color = input[1] or "rgb(255,255,255)" 591 | local type = tonumber(input[2]) 592 | 593 | 594 | local r, g, b = string.match(color, "rgb%((%d+), (%d+), (%d+)%)") 595 | 596 | r = tonumber(r) 597 | g = tonumber(g) 598 | b = tonumber(b) 599 | 600 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 601 | 602 | lib.setVehicleProperties(vehicle, { color1 = { r, g, b } }) 603 | 604 | SetVehicleModColor_1(vehicle, type, 0) 605 | openColorMenu() 606 | 607 | local newModData = { 608 | modLabel = locale("primary_color_title"), 609 | modType = "color1", 610 | modLevel = "rgb (" .. math.floor(r) .. " " .. math.floor(g) .. " " .. math.floor(b) .. ")", 611 | modPrice = price, 612 | } 613 | 614 | local foundMatch = false 615 | for i, existingModData in ipairs(cart) do 616 | if existingModData.modType == "color1" then 617 | cart[i] = newModData 618 | foundMatch = true 619 | break 620 | end 621 | end 622 | 623 | if not foundMatch then 624 | table.insert(cart, newModData) 625 | end 626 | 627 | currentVehProperties.new = getVehicleProperties(vehicle) 628 | 629 | 630 | lib.hideTextUI() 631 | showVehicleStats() 632 | end, 633 | }, 634 | { 635 | title = locale("secondary_color_title"), 636 | icon = mods.color.icon, 637 | iconColor = "rgba(244, 196, 48, 1.0)", 638 | description = price .. "$", 639 | onSelect = function() 640 | local input = lib.inputDialog(locale("select_color"), { 641 | { type = 'color', label = locale("color_input"), format = "rgb" }, 642 | { 643 | type = 'select', 644 | label = locale("color_type"), 645 | default = "0", 646 | clearable = true, 647 | options = { 648 | { value = "0", label = locale("color_type_normal") }, 649 | { value = "1", label = locale("color_type_metalic") }, 650 | { value = "2", label = locale("color_type_pearl") }, 651 | { value = "3", label = locale("color_type_matte") }, 652 | { value = "4", label = locale("color_type_metal") }, 653 | { value = "5", label = locale("color_type_chrome") }, 654 | } 655 | }, 656 | }) 657 | 658 | 659 | if not input then 660 | openColorMenu() 661 | return 662 | end 663 | 664 | local color = input[1] or "rgb(255,255,255)" 665 | local type = tonumber(input[2]) 666 | 667 | local r, g, b = string.match(color, "rgb%((%d+), (%d+), (%d+)%)") 668 | r = tonumber(r) 669 | g = tonumber(g) 670 | b = tonumber(b) 671 | 672 | lib.setVehicleProperties(vehicle, { color2 = { r, g, b } }) 673 | SetVehicleModColor_2(vehicle, type, 0) 674 | openColorMenu() 675 | 676 | local newModData = { 677 | modLabel = locale("secondary_color_title"), 678 | modType = "color2", 679 | modLevel = "rgb (" .. math.floor(r) .. " " .. math.floor(g) .. " " .. math.floor(b) .. ")", 680 | modPrice = price, 681 | } 682 | 683 | local foundMatch = false 684 | for i, existingModData in ipairs(cart) do 685 | if existingModData.modType == "color2" then 686 | cart[i] = newModData 687 | foundMatch = true 688 | break 689 | end 690 | end 691 | 692 | if not foundMatch then 693 | table.insert(cart, newModData) 694 | end 695 | 696 | currentVehProperties.new = getVehicleProperties(vehicle) 697 | 698 | 699 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 700 | end, 701 | }, 702 | { 703 | title = locale("pearlescent_color_title"), 704 | icon = 'droplet', 705 | iconColor = "rgba(236, 88, 0, 1.0)", 706 | onSelect = function() 707 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 708 | openPearlescentMenu() 709 | end, 710 | }, 711 | } 712 | }) 713 | 714 | lib.showContext('colorMenu') 715 | end 716 | 717 | 718 | local function bodyPartsMenu() 719 | lib.registerContext({ 720 | id = 'bodyPartsMenu', 721 | title = locale("cosmetics_title"), 722 | menu = "cosmeticsMenu", 723 | onBack = function() 724 | 725 | end, 726 | onExit = onExit, 727 | options = { 728 | { 729 | title = locale("spoiler_title"), 730 | icon = mods.modSpoilers.icon or 'wind', 731 | iconColor = getVehicleColor(), 732 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSpoilers.modNum) > 0), 733 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSpoilers.modNum)), 734 | onSelect = function() 735 | local vehicle = cache.vehicle 736 | 737 | local mod = mods.modSpoilers.modNum 738 | 739 | local mods = getVehicleModCounts(vehicle, mod) 740 | 741 | openModsMenu(vehicle, mod, mods) 742 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 743 | end, 744 | }, 745 | { 746 | title = locale("front_bumper_title"), 747 | icon = mods.modFrontBumper.icon or 'car-rear', 748 | iconColor = getVehicleColor(), 749 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modFrontBumper.modNum) > 0), 750 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modFrontBumper.modNum)), 751 | onSelect = function() 752 | local vehicle = cache.vehicle 753 | 754 | local mod = mods.modFrontBumper.modNum 755 | local mods = getVehicleModCounts(vehicle, mod) 756 | 757 | openModsMenu(vehicle, mod, mods) 758 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 759 | end, 760 | }, 761 | { 762 | title = locale("rear_bumper_title"), 763 | icon = mods.modRearBumper.icon or 'car-rear', 764 | iconColor = getVehicleColor(), 765 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modRearBumper.modNum) > 0), 766 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modRearBumper.modNum)), 767 | onSelect = function() 768 | local vehicle = cache.vehicle 769 | 770 | local mod = mods.modRearBumper.modNum 771 | local mods = getVehicleModCounts(vehicle, mod) 772 | 773 | openModsMenu(vehicle, mod, mods) 774 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 775 | end, 776 | }, 777 | { 778 | title = locale("side_skirt_title"), 779 | icon = mods.modSideSkirt.icon or 'car-side', 780 | iconColor = getVehicleColor(), 781 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSideSkirt.modNum) > 0), 782 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSideSkirt.modNum)), 783 | onSelect = function() 784 | local vehicle = cache.vehicle 785 | 786 | local mod = mods.modSideSkirt.modNum 787 | local mods = getVehicleModCounts(vehicle, mod) 788 | 789 | openModsMenu(vehicle, mod, mods) 790 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 791 | end, 792 | }, 793 | { 794 | title = locale("exhaust_title"), 795 | icon = mods.modExhaust.icon or 'car', 796 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modExhaust.modNum) > 0), 797 | iconColor = getVehicleColor(), 798 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modExhaust.modNum)), 799 | onSelect = function() 800 | local vehicle = cache.vehicle 801 | 802 | local mod = mods.modExhaust.modNum 803 | local mods = getVehicleModCounts(vehicle, mod) 804 | 805 | openModsMenu(vehicle, mod, mods) 806 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 807 | end, 808 | }, 809 | { 810 | title = locale("cage_title"), 811 | icon = mods.modFrame.icon or 'car', 812 | iconColor = getVehicleColor(), 813 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modFrame.modNum) > 0), 814 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modFrame.modNum)), 815 | onSelect = function() 816 | local vehicle = cache.vehicle 817 | 818 | local mod = mods.modFrame.modNum 819 | local mods = getVehicleModCounts(vehicle, mod) 820 | 821 | openModsMenu(vehicle, mod, mods) 822 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 823 | end, 824 | }, 825 | { 826 | title = locale("grille_title"), 827 | icon = mods.modGrille.icon or 'car', 828 | iconColor = getVehicleColor(), 829 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modGrille.modNum) > 0), 830 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modGrille.modNum)), 831 | onSelect = function() 832 | local vehicle = cache.vehicle 833 | 834 | local mod = mods.modGrille.modNum 835 | local mods = getVehicleModCounts(vehicle, mod) 836 | 837 | openModsMenu(vehicle, mod, mods) 838 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 839 | end, 840 | }, 841 | { 842 | title = locale("hood_title"), 843 | icon = mods.modHood.icon or 'car', 844 | iconColor = getVehicleColor(), 845 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modHood.modNum) > 0), 846 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modHood.modNum)), 847 | onSelect = function() 848 | local vehicle = cache.vehicle 849 | 850 | local mod = mods.modHood.modNum 851 | local mods = getVehicleModCounts(vehicle, mod) 852 | 853 | openModsMenu(vehicle, mod, mods) 854 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 855 | end, 856 | }, 857 | { 858 | title = locale("left_fender_title"), 859 | icon = mods.modFender.icon or 'car-side', 860 | iconColor = getVehicleColor(), 861 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modFender.modNum) > 0), 862 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modFender.modNum)), 863 | onSelect = function() 864 | local vehicle = cache.vehicle 865 | 866 | local mod = mods.modFender.modNum 867 | local mods = getVehicleModCounts(vehicle, mod) 868 | 869 | openModsMenu(vehicle, mod, mods) 870 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 871 | end, 872 | }, 873 | { 874 | title = locale("right_fender_title"), 875 | icon = mods.modRightFender.icon or 'car-side', 876 | iconColor = getVehicleColor(), 877 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modRightFender.modNum) > 0), 878 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modRightFender.modNum)), 879 | onSelect = function() 880 | local vehicle = cache.vehicle 881 | 882 | local mod = mods.modRightFender.modNum 883 | local mods = getVehicleModCounts(vehicle, mod) 884 | 885 | openModsMenu(vehicle, mod, mods) 886 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 887 | end, 888 | }, 889 | { 890 | title = locale("roof_title"), 891 | icon = mods.modRoof.icon or 'car', 892 | iconColor = getVehicleColor(), 893 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modRoof.modNum) > 0), 894 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modRoof.modNum)), 895 | onSelect = function() 896 | local vehicle = cache.vehicle 897 | 898 | local mod = mods.modRoof.modNum 899 | local mods = getVehicleModCounts(vehicle, mod) 900 | 901 | openModsMenu(vehicle, mod, mods) 902 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 903 | end, 904 | }, 905 | } 906 | }) 907 | 908 | lib.showContext('bodyPartsMenu') 909 | end 910 | 911 | local function windowTintMenu() 912 | local vehicle = cache.vehicle 913 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 914 | 915 | lib.registerContext({ 916 | id = 'windowTint', 917 | title = locale("window_tint_title"), 918 | menu = "cosmeticsMenu", 919 | onExit = onExit, 920 | options = { 921 | { 922 | title = locale("tint_pure_black"), 923 | icon = mods.windowTint.icon, 924 | iconColor = getVehicleColor(), 925 | disabled = getVehicleProperties(vehicle).windowTint == 1, 926 | onSelect = function() 927 | local mod = 1 928 | 929 | lib.setVehicleProperties(vehicle, { windowTint = mod }) 930 | 931 | local modPercentage = mods.windowTint.price / 100 932 | local price = vehiclePrice * modPercentage 933 | 934 | local newModData = { 935 | modLabel = locale("tint_pure_black"), 936 | modType = "windowTint", 937 | modLevel = " ", 938 | modPrice = price, 939 | } 940 | 941 | local foundMatch = false 942 | for i, existingModData in ipairs(cart) do 943 | if existingModData.modType == "windowTint" then 944 | cart[i] = newModData 945 | foundMatch = true 946 | break 947 | end 948 | end 949 | 950 | if not foundMatch then 951 | table.insert(cart, newModData) 952 | end 953 | currentVehProperties.new = getVehicleProperties(vehicle) 954 | 955 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 956 | windowTintMenu() 957 | end, 958 | }, 959 | { 960 | title = locale("tint_darksmoke"), 961 | icon = mods.windowTint.icon, 962 | iconColor = getVehicleColor(), 963 | disabled = getVehicleProperties(vehicle).windowTint == 2, 964 | onSelect = function() 965 | local mod = 2 966 | 967 | lib.setVehicleProperties(vehicle, { windowTint = mod }) 968 | 969 | 970 | local modPercentage = mods.windowTint.price / 100 971 | local price = vehiclePrice * modPercentage 972 | 973 | local newModData = { 974 | modLabel = locale("tint_darksmoke"), 975 | modType = "windowTint", 976 | modLevel = " ", 977 | modPrice = price, 978 | } 979 | 980 | local foundMatch = false 981 | for i, existingModData in ipairs(cart) do 982 | if existingModData.modType == "windowTint" then 983 | cart[i] = newModData 984 | foundMatch = true 985 | break 986 | end 987 | end 988 | 989 | if not foundMatch then 990 | table.insert(cart, newModData) 991 | end 992 | currentVehProperties.new = getVehicleProperties(vehicle) 993 | 994 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 995 | windowTintMenu() 996 | end, 997 | }, 998 | { 999 | title = locale("tint_lightsmoke"), 1000 | icon = mods.windowTint.icon, 1001 | iconColor = getVehicleColor(), 1002 | disabled = getVehicleProperties(vehicle).windowTint == 3, 1003 | onSelect = function() 1004 | local mod = 3 1005 | 1006 | local vehicle = cache.vehicle 1007 | 1008 | lib.setVehicleProperties(vehicle, { windowTint = mod }) 1009 | 1010 | local modPercentage = mods.windowTint.price / 100 1011 | local price = vehiclePrice * modPercentage 1012 | 1013 | local newModData = { 1014 | modLabel = locale("tint_lightsmoke"), 1015 | modType = "windowTint", 1016 | modLevel = " ", 1017 | modPrice = price, 1018 | } 1019 | 1020 | local foundMatch = false 1021 | for i, existingModData in ipairs(cart) do 1022 | if existingModData.modType == "windowTint" then 1023 | cart[i] = newModData 1024 | foundMatch = true 1025 | break 1026 | end 1027 | end 1028 | 1029 | if not foundMatch then 1030 | table.insert(cart, newModData) 1031 | end 1032 | currentVehProperties.new = getVehicleProperties(vehicle) 1033 | 1034 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1035 | windowTintMenu() 1036 | end, 1037 | }, 1038 | { 1039 | title = locale("tint_limo"), 1040 | icon = mods.windowTint.icon, 1041 | iconColor = getVehicleColor(), 1042 | disabled = getVehicleProperties(vehicle).windowTint == 4, 1043 | onSelect = function() 1044 | local mod = 4 1045 | 1046 | lib.setVehicleProperties(vehicle, { windowTint = mod }) 1047 | 1048 | local modPercentage = mods.windowTint.price / 100 1049 | local price = vehiclePrice * modPercentage 1050 | 1051 | local newModData = { 1052 | modLabel = locale("tint_limo"), 1053 | modType = "windowTint", 1054 | modLevel = " ", 1055 | modPrice = price, 1056 | } 1057 | 1058 | local foundMatch = false 1059 | for i, existingModData in ipairs(cart) do 1060 | if existingModData.modType == "windowTint" then 1061 | cart[i] = newModData 1062 | foundMatch = true 1063 | break 1064 | end 1065 | end 1066 | 1067 | if not foundMatch then 1068 | table.insert(cart, newModData) 1069 | end 1070 | currentVehProperties.new = getVehicleProperties(vehicle) 1071 | 1072 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1073 | windowTintMenu() 1074 | end, 1075 | }, 1076 | { 1077 | title = locale("tint_green"), 1078 | icon = mods.windowTint.icon, 1079 | iconColor = getVehicleColor(), 1080 | disabled = getVehicleProperties(vehicle).windowTint == 5, 1081 | onSelect = function() 1082 | local mod = 5 1083 | 1084 | lib.setVehicleProperties(vehicle, { windowTint = mod }) 1085 | 1086 | local modPercentage = mods.windowTint.price / 100 1087 | local price = vehiclePrice * modPercentage 1088 | 1089 | local newModData = { 1090 | modLabel = locale("tint_green"), 1091 | modType = "windowTint", 1092 | modLevel = " ", 1093 | modPrice = price, 1094 | } 1095 | 1096 | local foundMatch = false 1097 | for i, existingModData in ipairs(cart) do 1098 | if existingModData.modType == "windowTint" then 1099 | cart[i] = newModData 1100 | foundMatch = true 1101 | break 1102 | end 1103 | end 1104 | 1105 | if not foundMatch then 1106 | table.insert(cart, newModData) 1107 | end 1108 | currentVehProperties.new = getVehicleProperties(vehicle) 1109 | 1110 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1111 | windowTintMenu() 1112 | end, 1113 | }, 1114 | } 1115 | }) 1116 | 1117 | lib.showContext('windowTint') 1118 | end 1119 | 1120 | local function platesColorMenu() 1121 | local vehicle = cache.vehicle 1122 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 1123 | 1124 | lib.registerContext({ 1125 | id = 'platesColorMenu', 1126 | title = locale("plate_color_title"), 1127 | menu = "cosmeticsMenu", 1128 | onExit = onExit, 1129 | options = { 1130 | { 1131 | title = locale("plate_blue_on_white1"), 1132 | icon = mods.plateIndex.icon, 1133 | iconColor = getVehicleColor(), 1134 | disabled = getVehicleProperties(vehicle).plateIndex == 0, 1135 | onSelect = function() 1136 | local mod = 0 1137 | 1138 | local properties = {} 1139 | properties[mods.plateIndex.modNum] = mod 1140 | 1141 | lib.setVehicleProperties(vehicle, properties) 1142 | 1143 | local modPercentage = mods.plateIndex.price / 100 1144 | local price = vehiclePrice * modPercentage 1145 | 1146 | local newModData = { 1147 | modLabel = locale("plate_blue_on_white1"), 1148 | modType = "plateIndex", 1149 | modLevel = " ", 1150 | modPrice = price, 1151 | } 1152 | 1153 | local foundMatch = false 1154 | for i, existingModData in ipairs(cart) do 1155 | if existingModData.modType == "plateIndex" then 1156 | cart[i] = newModData 1157 | foundMatch = true 1158 | break 1159 | end 1160 | end 1161 | 1162 | if not foundMatch then 1163 | table.insert(cart, newModData) 1164 | end 1165 | currentVehProperties.new = getVehicleProperties(vehicle) 1166 | 1167 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1168 | platesColorMenu() 1169 | end, 1170 | }, 1171 | { 1172 | title = locale("plate_yellow_black"), 1173 | icon = mods.plateIndex.icon, 1174 | iconColor = getVehicleColor(), 1175 | disabled = getVehicleProperties(vehicle).plateIndex == 1, 1176 | onSelect = function() 1177 | local mod = 1 1178 | 1179 | local vehicle = cache.vehicle 1180 | 1181 | local properties = {} 1182 | properties[mods.plateIndex.modNum] = mod 1183 | 1184 | lib.setVehicleProperties(vehicle, properties) 1185 | 1186 | local modPercentage = mods.plateIndex.price / 100 1187 | local price = vehiclePrice * modPercentage 1188 | 1189 | local newModData = { 1190 | modLabel = locale("plate_blue_on_white1"), 1191 | modType = "plateIndex", 1192 | modLevel = " ", 1193 | modPrice = price, 1194 | } 1195 | 1196 | local foundMatch = false 1197 | for i, existingModData in ipairs(cart) do 1198 | if existingModData.modType == "plateIndex" then 1199 | cart[i] = newModData 1200 | foundMatch = true 1201 | break 1202 | end 1203 | end 1204 | 1205 | if not foundMatch then 1206 | table.insert(cart, newModData) 1207 | end 1208 | currentVehProperties.new = getVehicleProperties(vehicle) 1209 | 1210 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1211 | platesColorMenu() 1212 | end, 1213 | }, 1214 | { 1215 | title = locale("plate_yellow_blue"), 1216 | icon = mods.plateIndex.icon, 1217 | iconColor = getVehicleColor(), 1218 | disabled = getVehicleProperties(vehicle).plateIndex == 2, 1219 | onSelect = function() 1220 | local mod = 2 1221 | 1222 | local vehicle = cache.vehicle 1223 | 1224 | local properties = {} 1225 | properties[mods.plateIndex.modNum] = mod 1226 | 1227 | lib.setVehicleProperties(vehicle, properties) 1228 | 1229 | local modPercentage = mods.plateIndex.price / 100 1230 | local price = vehiclePrice * modPercentage 1231 | 1232 | local newModData = { 1233 | modLabel = locale("plate_blue_on_white1"), 1234 | modType = "plateIndex", 1235 | modLevel = " ", 1236 | modPrice = price, 1237 | } 1238 | 1239 | local foundMatch = false 1240 | for i, existingModData in ipairs(cart) do 1241 | if existingModData.modType == "plateIndex" then 1242 | cart[i] = newModData 1243 | foundMatch = true 1244 | break 1245 | end 1246 | end 1247 | 1248 | if not foundMatch then 1249 | table.insert(cart, newModData) 1250 | end 1251 | currentVehProperties.new = getVehicleProperties(vehicle) 1252 | 1253 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1254 | platesColorMenu() 1255 | end, 1256 | }, 1257 | { 1258 | title = locale("plate_blue_on_white2"), 1259 | icon = mods.plateIndex.icon, 1260 | iconColor = getVehicleColor(), 1261 | disabled = getVehicleProperties(vehicle).plateIndex == 3, 1262 | onSelect = function() 1263 | local mod = 3 1264 | 1265 | local vehicle = cache.vehicle 1266 | 1267 | local properties = {} 1268 | properties[mods.plateIndex.modNum] = mod 1269 | 1270 | lib.setVehicleProperties(vehicle, properties) 1271 | 1272 | local modPercentage = mods.plateIndex.price / 100 1273 | local price = vehiclePrice * modPercentage 1274 | 1275 | local newModData = { 1276 | modLabel = locale("plate_blue_on_white1"), 1277 | modType = "plateIndex", 1278 | modLevel = " ", 1279 | modPrice = price, 1280 | } 1281 | 1282 | local foundMatch = false 1283 | for i, existingModData in ipairs(cart) do 1284 | if existingModData.modType == "plateIndex" then 1285 | cart[i] = newModData 1286 | foundMatch = true 1287 | break 1288 | end 1289 | end 1290 | 1291 | if not foundMatch then 1292 | table.insert(cart, newModData) 1293 | end 1294 | currentVehProperties.new = getVehicleProperties(vehicle) 1295 | 1296 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1297 | platesColorMenu() 1298 | end, 1299 | }, 1300 | { 1301 | title = locale("plate_blue_on_white3"), 1302 | icon = mods.plateIndex.icon, 1303 | iconColor = getVehicleColor(), 1304 | disabled = getVehicleProperties(vehicle).plateIndex == 4, 1305 | onSelect = function() 1306 | local mod = 4 1307 | 1308 | local vehicle = cache.vehicle 1309 | 1310 | local properties = {} 1311 | properties[mods.plateIndex.modNum] = mod 1312 | 1313 | lib.setVehicleProperties(vehicle, properties) 1314 | 1315 | local modPercentage = mods.plateIndex.price / 100 1316 | local price = vehiclePrice * modPercentage 1317 | 1318 | local newModData = { 1319 | modLabel = locale("plate_blue_on_white1"), 1320 | modType = "plateIndex", 1321 | modLevel = " ", 1322 | modPrice = price, 1323 | } 1324 | 1325 | local foundMatch = false 1326 | for i, existingModData in ipairs(cart) do 1327 | if existingModData.modType == "plateIndex" then 1328 | cart[i] = newModData 1329 | foundMatch = true 1330 | break 1331 | end 1332 | end 1333 | 1334 | if not foundMatch then 1335 | table.insert(cart, newModData) 1336 | end 1337 | currentVehProperties.new = getVehicleProperties(vehicle) 1338 | 1339 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1340 | platesColorMenu() 1341 | end, 1342 | }, 1343 | } 1344 | }) 1345 | 1346 | lib.showContext('platesColorMenu') 1347 | end 1348 | 1349 | 1350 | local function wheelColors() 1351 | local options = {} 1352 | local vehicle = cache.vehicle 1353 | local colors = colors.pearlescent 1354 | 1355 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 1356 | local modPercentage = mods.wheelsColor.price / 100 1357 | local price = vehiclePrice * modPercentage 1358 | 1359 | for i = 1, #colors, 1 do 1360 | table.insert(options, 1361 | { 1362 | title = colors[i].category, 1363 | icon = 'paint-roller', 1364 | iconColor = colors[i].color, 1365 | description = price .. "$", 1366 | onSelect = function() 1367 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1368 | local options = {} 1369 | 1370 | for j = 1, #colors[i].colors do 1371 | local disabled = false 1372 | 1373 | if getVehicleProperties(vehicle).wheelColor == colors[i].colors[j].index then 1374 | disabled = true 1375 | end 1376 | 1377 | table.insert(options, 1378 | { 1379 | title = colors[i].colors[j].label, 1380 | icon = 'droplet', 1381 | iconColor = colors[i].colors[j].iconColor, 1382 | disabled = disabled, 1383 | onSelect = function() 1384 | lib.setVehicleProperties(vehicle, { wheelColor = colors[i].colors[j].index }) 1385 | 1386 | 1387 | local newModData = { 1388 | modLabel = colors[i].colors[j].label, 1389 | modType = "wheelColor", 1390 | modLevel = " ", 1391 | modPrice = price, 1392 | } 1393 | 1394 | local foundMatch = false 1395 | for i, existingModData in ipairs(cart) do 1396 | if existingModData.modType == "wheelColor" then 1397 | cart[i] = newModData 1398 | foundMatch = true 1399 | break 1400 | end 1401 | end 1402 | 1403 | if not foundMatch then 1404 | table.insert(cart, newModData) 1405 | end 1406 | currentVehProperties.new = getVehicleProperties(vehicle) 1407 | 1408 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 1409 | wheelColors() 1410 | end 1411 | 1412 | } 1413 | ) 1414 | end 1415 | 1416 | lib.registerContext({ 1417 | id = colors[i].category, 1418 | title = colors[i].category, 1419 | menu = "wheelColorCategory", 1420 | onExit = function() 1421 | lib.hideTextUI() 1422 | confirmPayment() 1423 | end, 1424 | options = options 1425 | }) 1426 | 1427 | lib.showContext(colors[i].category) 1428 | end, 1429 | } 1430 | ) 1431 | end 1432 | 1433 | lib.registerContext({ 1434 | id = 'wheelColorCategory', 1435 | title = locale("wheel_color_title"), 1436 | menu = "wheelsMenu", 1437 | onExit = onExit, 1438 | options = options 1439 | }) 1440 | lib.showContext('wheelColorCategory') 1441 | end 1442 | 1443 | local function openWheelsCategory() 1444 | lib.registerContext({ 1445 | id = 'wheelsCategory', 1446 | title = locale("wheel_type_title"), 1447 | menu = "wheelsMenu", 1448 | onExit = onExit, 1449 | options = { 1450 | { 1451 | title = locale("wheel_type_sport"), 1452 | icon = "dharmachakra", 1453 | iconColor = getVehicleColor(), 1454 | onSelect = function() 1455 | local vehicle = cache.vehicle 1456 | lib.setVehicleProperties(vehicle, { wheels = 5 }) 1457 | 1458 | local mod = mods.modFrontWheel0.modNum 1459 | local mods = getVehicleModCounts(vehicle, mod) 1460 | 1461 | openModsMenu(vehicle, mod, mods) 1462 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1463 | end 1464 | }, 1465 | { 1466 | title = locale("wheel_type_muscle"), 1467 | icon = "dharmachakra", 1468 | iconColor = getVehicleColor(), 1469 | onSelect = function() 1470 | local vehicle = cache.vehicle 1471 | lib.setVehicleProperties(vehicle, { wheels = 1 }) 1472 | 1473 | local mod = mods.modFrontWheel1.modNum 1474 | local mods = getVehicleModCounts(vehicle, mod) 1475 | 1476 | openModsMenu(vehicle, mod, mods) 1477 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1478 | end 1479 | }, 1480 | { 1481 | title = locale("wheel_type_lowrider"), 1482 | icon = "dharmachakra", 1483 | iconColor = getVehicleColor(), 1484 | onSelect = function() 1485 | local vehicle = cache.vehicle 1486 | lib.setVehicleProperties(vehicle, { wheels = 2 }) 1487 | 1488 | local mod = mods.modFrontWheel2.modNum 1489 | local mods = getVehicleModCounts(vehicle, mod) 1490 | 1491 | openModsMenu(vehicle, mod, mods) 1492 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1493 | end 1494 | }, 1495 | { 1496 | title = locale("wheel_type_suv"), 1497 | icon = "dharmachakra", 1498 | iconColor = getVehicleColor(), 1499 | onSelect = function() 1500 | local vehicle = cache.vehicle 1501 | lib.setVehicleProperties(vehicle, { wheels = 3 }) 1502 | 1503 | local mod = mods.modFrontWheel3.modNum 1504 | local mods = getVehicleModCounts(vehicle, mod) 1505 | 1506 | openModsMenu(vehicle, mod, mods) 1507 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1508 | end 1509 | }, 1510 | { 1511 | title = locale("wheel_type_offroad"), 1512 | icon = "dharmachakra", 1513 | iconColor = getVehicleColor(), 1514 | onSelect = function() 1515 | local vehicle = cache.vehicle 1516 | lib.setVehicleProperties(vehicle, { wheels = 4 }) 1517 | 1518 | local mod = mods.modFrontWheel4.modNum 1519 | local mods = getVehicleModCounts(vehicle, mod) 1520 | 1521 | openModsMenu(vehicle, mod, mods) 1522 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1523 | end 1524 | }, 1525 | { 1526 | title = locale("wheel_type_tuner"), 1527 | icon = "dharmachakra", 1528 | iconColor = getVehicleColor(), 1529 | onSelect = function() 1530 | local vehicle = cache.vehicle 1531 | lib.setVehicleProperties(vehicle, { wheels = 5 }) 1532 | 1533 | local mod = mods.modFrontWheel5.modNum 1534 | local mods = getVehicleModCounts(vehicle, mod) 1535 | 1536 | openModsMenu(vehicle, mod, mods) 1537 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1538 | end 1539 | }, 1540 | { 1541 | title = locale("wheel_type_bike"), 1542 | icon = "dharmachakra", 1543 | iconColor = getVehicleColor(), 1544 | onSelect = function() 1545 | local vehicle = cache.vehicle 1546 | 1547 | lib.setVehicleProperties(vehicle, { wheels = 6 }) 1548 | 1549 | local mod = mods.modFrontWheel6.modNum 1550 | local mods = getVehicleModCounts(vehicle, mod) 1551 | 1552 | openModsMenu(vehicle, mod, mods) 1553 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1554 | end 1555 | }, 1556 | { 1557 | title = locale("wheel_type_highend"), 1558 | icon = "dharmachakra", 1559 | iconColor = getVehicleColor(), 1560 | onSelect = function() 1561 | local vehicle = cache.vehicle 1562 | lib.setVehicleProperties(vehicle, { wheels = 7 }) 1563 | 1564 | local mod = mods.modFrontWheel7.modNum 1565 | local mods = getVehicleModCounts(vehicle, mod) 1566 | 1567 | openModsMenu(vehicle, mod, mods) 1568 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1569 | end 1570 | }, 1571 | } 1572 | }) 1573 | lib.showContext('wheelsCategory') 1574 | end 1575 | 1576 | local function openWheelsMenu() 1577 | local vehicle = cache.vehicle 1578 | 1579 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 1580 | local modPercentage = mods.wheelsColor.price / 100 1581 | local price = vehiclePrice * modPercentage 1582 | 1583 | lib.registerContext({ 1584 | id = 'wheelsMenu', 1585 | title = locale("wheel_menu_title"), 1586 | menu = "cosmeticsMenu", 1587 | onBack = function() 1588 | 1589 | end, 1590 | onExit = onExit, 1591 | options = { 1592 | { 1593 | title = locale("wheel_color_title"), 1594 | icon = "brush", 1595 | iconColor = getVehicleColor(), 1596 | onSelect = function() 1597 | wheelColors() 1598 | end 1599 | }, 1600 | { 1601 | title = locale("wheel_smoke_title"), 1602 | icon = "cloud", 1603 | iconColor = getVehicleColor(), 1604 | description = price .. "$", 1605 | onSelect = function() 1606 | local input = lib.inputDialog(locale("select_color"), { 1607 | { type = 'color', label = locale("color_input"), format = "rgb" }, 1608 | }) 1609 | 1610 | if not input then 1611 | openWheelsMenu() 1612 | return 1613 | end 1614 | 1615 | local color = input[1] or "rgb(255,255,255)" 1616 | 1617 | local r, g, b = string.match(color, "rgb%((%d+), (%d+), (%d+)%)") 1618 | r = tonumber(r) 1619 | g = tonumber(g) 1620 | b = tonumber(b) 1621 | 1622 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 1623 | 1624 | local newModData = { 1625 | modLabel = locale("wheel_smoke_title"), 1626 | modType = "tyreSmokeColor", 1627 | modLevel = " ", 1628 | modPrice = price, 1629 | } 1630 | 1631 | local foundMatch = false 1632 | for i, existingModData in ipairs(cart) do 1633 | if existingModData.modType == "tyreSmokeColor" then 1634 | cart[i] = newModData 1635 | foundMatch = true 1636 | break 1637 | end 1638 | end 1639 | 1640 | if not foundMatch then 1641 | table.insert(cart, newModData) 1642 | end 1643 | 1644 | lib.setVehicleProperties(vehicle, { modSmokeEnabled = true }) 1645 | lib.setVehicleProperties(vehicle, { tyreSmokeColor = { r, g, b } }) 1646 | 1647 | currentVehProperties.new = getVehicleProperties(vehicle) 1648 | openWheelsMenu() 1649 | end 1650 | }, 1651 | { 1652 | title = locale("wheel_type_title"), 1653 | icon = "dharmachakra", 1654 | iconColor = getVehicleColor(), 1655 | onSelect = function() 1656 | openWheelsCategory() 1657 | end 1658 | }, 1659 | } 1660 | }) 1661 | 1662 | lib.showContext('wheelsMenu') 1663 | end 1664 | 1665 | 1666 | local function openNeonMenu() 1667 | local vehicle = cache.vehicle 1668 | local disabled = getVehicleProperties(vehicle).neonEnabled 1669 | local vehiclePrice = getVehiclePrice(vehicle) or 50000 1670 | 1671 | if not disabled[1] then disabled = true else disabled = false end 1672 | 1673 | local modPercentage = mods.neon.price / 100 1674 | 1675 | local price = vehiclePrice * modPercentage 1676 | 1677 | 1678 | lib.registerContext({ 1679 | id = 'neonMenu', 1680 | title = locale("neon_title"), 1681 | menu = "cosmeticsMenu", 1682 | onExit = onExit, 1683 | options = { 1684 | { 1685 | title = locale("disable_neon"), 1686 | disabled = disabled, 1687 | description = price .. "$", 1688 | onSelect = function() 1689 | lib.setVehicleProperties(vehicle, { neonEnabled = { false, false, false, false } }) 1690 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 1691 | 1692 | local newModData = { 1693 | modLabel = locale("disable_neon"), 1694 | modType = "neonColor", 1695 | modLevel = "", 1696 | modPrice = price, 1697 | } 1698 | 1699 | local foundMatch = false 1700 | for i, existingModData in ipairs(cart) do 1701 | if existingModData.modType == "neonColor" then 1702 | cart[i] = newModData 1703 | foundMatch = true 1704 | break 1705 | end 1706 | end 1707 | 1708 | if not foundMatch then 1709 | table.insert(cart, newModData) 1710 | end 1711 | currentVehProperties.new = getVehicleProperties(vehicle) 1712 | 1713 | openNeonMenu() 1714 | end 1715 | }, 1716 | { 1717 | title = locale("color_neon"), 1718 | description = price .. "$", 1719 | onSelect = function() 1720 | local input = lib.inputDialog(locale("select_color"), { 1721 | { type = 'color', label = locale("color_input"), format = "rgb" }, 1722 | }) 1723 | 1724 | if not input then 1725 | openColorMenu() 1726 | return 1727 | end 1728 | 1729 | local color = input[1] or "rgb(255,255,255)" 1730 | 1731 | local vehicle = cache.vehicle 1732 | 1733 | local r, g, b = string.match(color, "rgb%((%d+), (%d+), (%d+)%)") 1734 | r = tonumber(r) 1735 | g = tonumber(g) 1736 | b = tonumber(b) 1737 | 1738 | playSound('Zoom_In', 'DLC_HEIST_PLANNING_BOARD_SOUNDS') 1739 | 1740 | 1741 | local newModData = { 1742 | modLabel = " ", 1743 | modType = "neonColor", 1744 | modLevel = "rgb (" .. math.floor(r) .. " " .. math.floor(g) .. " " .. math.floor(b) .. ")", 1745 | modPrice = price, 1746 | } 1747 | 1748 | local foundMatch = false 1749 | for i, existingModData in ipairs(cart) do 1750 | if existingModData.modType == "neonColor" then 1751 | cart[i] = newModData 1752 | foundMatch = true 1753 | break 1754 | end 1755 | end 1756 | 1757 | if not foundMatch then 1758 | table.insert(cart, newModData) 1759 | end 1760 | 1761 | 1762 | lib.setVehicleProperties(vehicle, { neonEnabled = { true, true, true, true } }) 1763 | lib.setVehicleProperties(vehicle, { neonColor = { r, g, b } }) 1764 | 1765 | currentVehProperties.new = getVehicleProperties(vehicle) 1766 | 1767 | openNeonMenu() 1768 | end 1769 | }, 1770 | } 1771 | }) 1772 | 1773 | lib.showContext("neonMenu") 1774 | end 1775 | 1776 | local function openEstethicsMenu() 1777 | lib.registerContext({ 1778 | id = 'cosmeticsMenu', 1779 | title = locale("cosmetics_title"), 1780 | menu = "tuningMenu", 1781 | onExit = onExit, 1782 | options = { 1783 | { 1784 | title = locale("color_title"), 1785 | icon = 'paint-roller', 1786 | iconColor = getVehicleColor(), 1787 | onSelect = function() 1788 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1789 | openColorMenu() 1790 | end, 1791 | }, 1792 | { 1793 | title = locale("xenon_title"), 1794 | icon = 'lightbulb', 1795 | iconColor = getVehicleColor(), 1796 | onSelect = function() 1797 | openXenonMenu() 1798 | end, 1799 | }, 1800 | { 1801 | title = locale("neon_title"), 1802 | icon = 'lightbulb', 1803 | iconColor = getVehicleColor(), 1804 | onSelect = function() 1805 | openNeonMenu() 1806 | end, 1807 | }, 1808 | { 1809 | title = locale("body_parts_title"), 1810 | icon = 'wrench', 1811 | iconColor = getVehicleColor(), 1812 | onSelect = function() 1813 | bodyPartsMenu() 1814 | end, 1815 | }, 1816 | { 1817 | title = locale("wheels_title"), 1818 | icon = 'dharmachakra', 1819 | iconColor = getVehicleColor(), 1820 | onSelect = function() 1821 | openWheelsMenu() 1822 | end, 1823 | }, 1824 | { 1825 | title = locale("window_tint_title"), 1826 | icon = 'bullhorn', 1827 | iconColor = getVehicleColor(), 1828 | description = "5", 1829 | onSelect = function() 1830 | windowTintMenu() 1831 | end, 1832 | }, 1833 | { 1834 | title = locale("horn_title"), 1835 | icon = mods.modHorns.icon or 'bullhorn', 1836 | iconColor = getVehicleColor(), 1837 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modHorns.modNum) > 0), 1838 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modHorns.modNum)), 1839 | onSelect = function() 1840 | local vehicle = cache.vehicle 1841 | 1842 | local mod = mods.modHorns.modNum 1843 | local mods = getVehicleModCounts(vehicle, mod) 1844 | 1845 | openModsMenu(vehicle, mod, mods) 1846 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1847 | end, 1848 | }, 1849 | { 1850 | title = locale("plates_title"), 1851 | icon = 'credit-card', 1852 | iconColor = getVehicleColor(), 1853 | description = "5", 1854 | onSelect = function() 1855 | platesColorMenu() 1856 | end, 1857 | }, 1858 | { 1859 | title = locale("plate_holder_title"), 1860 | icon = mods.modPlateHolder.icon or 'credit-card', 1861 | iconColor = getVehicleColor(), 1862 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modPlateHolder.modNum) > 0), 1863 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modPlateHolder.modNum)), 1864 | onSelect = function() 1865 | local vehicle = cache.vehicle 1866 | 1867 | local mod = mods.modPlateHolder.modNum 1868 | local mods = getVehicleModCounts(vehicle, mod) 1869 | 1870 | openModsMenu(vehicle, mod, mods) 1871 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1872 | end, 1873 | }, 1874 | { 1875 | title = locale("plate_vanity_title"), 1876 | icon = mods.modVanityPlate.icon or 'credit-card', 1877 | iconColor = getVehicleColor(), 1878 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modVanityPlate.modNum) > 0), 1879 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modVanityPlate.modNum)), 1880 | onSelect = function() 1881 | local vehicle = cache.vehicle 1882 | 1883 | local mod = mods.modVanityPlate.modNum 1884 | local mods = getVehicleModCounts(vehicle, mod) 1885 | 1886 | openModsMenu(vehicle, mod, mods) 1887 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1888 | end, 1889 | }, 1890 | { 1891 | title = locale("interior_title"), 1892 | icon = mods.modTrimA.icon or 'credit-card', 1893 | iconColor = getVehicleColor(), 1894 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modTrimA.modNum) > 0), 1895 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modTrimA.modNum)), 1896 | onSelect = function() 1897 | local vehicle = cache.vehicle 1898 | 1899 | local mod = mods.modTrimA.modNum 1900 | local mods = getVehicleModCounts(vehicle, mod) 1901 | 1902 | openModsMenu(vehicle, mod, mods) 1903 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1904 | end, 1905 | }, 1906 | { 1907 | title = locale("trim_title"), 1908 | icon = mods.modOrnaments.icon or 'credit-card', 1909 | iconColor = getVehicleColor(), 1910 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modOrnaments.modNum) > 0), 1911 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modOrnaments.modNum)), 1912 | onSelect = function() 1913 | local vehicle = cache.vehicle 1914 | 1915 | local mod = mods.modOrnaments.modNum 1916 | local mods = getVehicleModCounts(vehicle, mod) 1917 | 1918 | openModsMenu(vehicle, mod, mods) 1919 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1920 | end, 1921 | }, 1922 | { 1923 | title = locale("dashboard_title"), 1924 | icon = mods.modDashboard.icon or 'credit-card', 1925 | iconColor = getVehicleColor(), 1926 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modDashboard.modNum) > 0), 1927 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modDashboard.modNum)), 1928 | onSelect = function() 1929 | local vehicle = cache.vehicle 1930 | 1931 | local mod = mods.modDashboard.modNum 1932 | local mods = getVehicleModCounts(vehicle, mod) 1933 | 1934 | openModsMenu(vehicle, mod, mods) 1935 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1936 | end, 1937 | }, 1938 | { 1939 | title = locale("speedometer_title"), 1940 | icon = mods.modDial.icon or 'credit-card', 1941 | iconColor = getVehicleColor(), 1942 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modDial.modNum) > 0), 1943 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modDial.modNum)), 1944 | onSelect = function() 1945 | local vehicle = cache.vehicle 1946 | 1947 | local mod = mods.modDial.modNum 1948 | local mods = getVehicleModCounts(vehicle, mod) 1949 | 1950 | openModsMenu(vehicle, mod, mods) 1951 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1952 | end, 1953 | }, 1954 | { 1955 | title = locale("door_speakers_title"), 1956 | icon = mods.modDoorSpeaker.icon or 'credit-card', 1957 | iconColor = getVehicleColor(), 1958 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modDoorSpeaker.modNum) > 0), 1959 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modDoorSpeaker.modNum)), 1960 | onSelect = function() 1961 | local vehicle = cache.vehicle 1962 | 1963 | local mod = mods.modDoorSpeaker.modNum 1964 | local mods = getVehicleModCounts(vehicle, mod) 1965 | 1966 | openModsMenu(vehicle, mod, mods) 1967 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1968 | end, 1969 | }, 1970 | { 1971 | title = locale("seats_title"), 1972 | icon = mods.modSeats.icon or 'credit-card', 1973 | iconColor = getVehicleColor(), 1974 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSeats.modNum) > 0), 1975 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSeats.modNum)), 1976 | onSelect = function() 1977 | local vehicle = cache.vehicle 1978 | 1979 | local mod = mods.modSeats.modNum 1980 | local mods = getVehicleModCounts(vehicle, mod) 1981 | 1982 | openModsMenu(vehicle, mod, mods) 1983 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 1984 | end, 1985 | }, 1986 | { 1987 | title = locale("steering_wheel_title"), 1988 | icon = mods.modSteeringWheel.icon or 'steering-wheel', 1989 | iconColor = getVehicleColor(), 1990 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSteeringWheel.modNum) > 0), 1991 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSteeringWheel.modNum)), 1992 | onSelect = function() 1993 | local vehicle = cache.vehicle 1994 | 1995 | local mod = mods.modSteeringWheel.modNum 1996 | local mods = getVehicleModCounts(vehicle, mod) 1997 | 1998 | openModsMenu(vehicle, mod, mods) 1999 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2000 | end, 2001 | }, 2002 | { 2003 | title = locale("gears_title"), 2004 | icon = mods.modShifterLeavers.icon or 'credit-card', 2005 | iconColor = getVehicleColor(), 2006 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modShifterLeavers.modNum) > 0), 2007 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modShifterLeavers.modNum)), 2008 | onSelect = function() 2009 | local vehicle = cache.vehicle 2010 | 2011 | local mod = mods.modShifterLeavers.modNum 2012 | local mods = getVehicleModCounts(vehicle, mod) 2013 | 2014 | openModsMenu(vehicle, mod, mods) 2015 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2016 | end, 2017 | }, 2018 | { 2019 | title = locale("quarter_deck_title"), 2020 | icon = mods.modAPlate.icon or 'credit-card', 2021 | iconColor = getVehicleColor(), 2022 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modAPlate.modNum) > 0), 2023 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modAPlate.modNum)), 2024 | onSelect = function() 2025 | local vehicle = cache.vehicle 2026 | 2027 | local mod = mods.modAPlate.modNum 2028 | local mods = getVehicleModCounts(vehicle, mod) 2029 | 2030 | openModsMenu(vehicle, mod, mods) 2031 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2032 | end, 2033 | }, 2034 | { 2035 | title = locale("speakers_title"), 2036 | icon = mods.modSpeakers.icon or 'credit-card', 2037 | iconColor = getVehicleColor(), 2038 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modSpeakers.modNum) > 0), 2039 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modSpeakers.modNum)), 2040 | onSelect = function() 2041 | local vehicle = cache.vehicle 2042 | 2043 | local mod = mods.modSpeakers.modNum 2044 | local mods = getVehicleModCounts(vehicle, mod) 2045 | 2046 | openModsMenu(vehicle, mod, mods) 2047 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2048 | end, 2049 | }, 2050 | { 2051 | title = locale("trunk_title"), 2052 | icon = mods.modTrunk.icon or 'credit-card', 2053 | iconColor = getVehicleColor(), 2054 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modTrunk.modNum) > 0), 2055 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modTrunk.modNum)), 2056 | onSelect = function() 2057 | local vehicle = cache.vehicle 2058 | 2059 | local mod = mods.modTrunk.modNum 2060 | local mods = getVehicleModCounts(vehicle, mod) 2061 | 2062 | openModsMenu(vehicle, mod, mods) 2063 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2064 | end, 2065 | }, 2066 | { 2067 | title = locale("hydrolic_title"), 2068 | icon = mods.modHydrolic.icon or 'credit-card', 2069 | iconColor = getVehicleColor(), 2070 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modHydrolic.modNum) > 0), 2071 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modHydrolic.modNum)), 2072 | onSelect = function() 2073 | local vehicle = cache.vehicle 2074 | 2075 | local mod = mods.modHydrolic.modNum 2076 | local mods = getVehicleModCounts(vehicle, mod) 2077 | 2078 | openModsMenu(vehicle, mod, mods) 2079 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2080 | end, 2081 | }, 2082 | { 2083 | title = locale("engine_block_title"), 2084 | icon = mods.modEngineBlock.icon or 'credit-card', 2085 | iconColor = getVehicleColor(), 2086 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modEngineBlock.modNum) > 0), 2087 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modEngineBlock.modNum)), 2088 | onSelect = function() 2089 | local vehicle = cache.vehicle 2090 | 2091 | local mod = mods.modEngineBlock.modNum 2092 | local mods = getVehicleModCounts(vehicle, mod) 2093 | 2094 | openModsMenu(vehicle, mod, mods) 2095 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2096 | end, 2097 | }, 2098 | { 2099 | title = locale("air_filter_title"), 2100 | icon = mods.modAirFilter.icon or 'credit-card', 2101 | iconColor = getVehicleColor(), 2102 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modAirFilter.modNum) > 0), 2103 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modAirFilter.modNum)), 2104 | onSelect = function() 2105 | local vehicle = cache.vehicle 2106 | 2107 | local mod = mods.modAirFilter.modNum 2108 | local mods = getVehicleModCounts(vehicle, mod) 2109 | 2110 | openModsMenu(vehicle, mod, mods) 2111 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2112 | end, 2113 | }, 2114 | { 2115 | title = locale("struts_title"), 2116 | icon = mods.modStruts.icon or 'credit-card', 2117 | iconColor = getVehicleColor(), 2118 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modStruts.modNum) > 0), 2119 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modStruts.modNum)), 2120 | onSelect = function() 2121 | local vehicle = cache.vehicle 2122 | 2123 | local mod = mods.modStruts.modNum 2124 | local mods = getVehicleModCounts(vehicle, mod) 2125 | 2126 | openModsMenu(vehicle, mod, mods) 2127 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2128 | end, 2129 | }, 2130 | { 2131 | title = locale("arch_cover"), 2132 | icon = mods.modArchCover.icon or 'credit-card', 2133 | iconColor = getVehicleColor(), 2134 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modArchCover.modNum) > 0), 2135 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modArchCover.modNum)), 2136 | onSelect = function() 2137 | local vehicle = cache.vehicle 2138 | 2139 | local mod = mods.modArchCover.modNum 2140 | local mods = getVehicleModCounts(vehicle, mod) 2141 | 2142 | openModsMenu(vehicle, mod, mods) 2143 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2144 | end, 2145 | }, 2146 | { 2147 | title = locale("aerials_title"), 2148 | icon = mods.modAerials.icon or 'credit-card', 2149 | iconColor = getVehicleColor(), 2150 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modAerials.modNum) > 0), 2151 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modAerials.modNum)), 2152 | onSelect = function() 2153 | local vehicle = cache.vehicle 2154 | 2155 | local mod = mods.modAerials.modNum 2156 | local mods = getVehicleModCounts(vehicle, mod) 2157 | 2158 | openModsMenu(vehicle, mod, mods) 2159 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2160 | end, 2161 | }, 2162 | { 2163 | title = locale("wings_title"), 2164 | icon = mods.modTrimB.icon or 'credit-card', 2165 | iconColor = getVehicleColor(), 2166 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modTrimB.modNum) > 0), 2167 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modTrimB.modNum)), 2168 | onSelect = function() 2169 | local vehicle = cache.vehicle 2170 | 2171 | local mod = mods.modTrimB.modNum 2172 | local mods = getVehicleModCounts(vehicle, mod) 2173 | 2174 | openModsMenu(vehicle, mod, mods) 2175 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2176 | end, 2177 | }, 2178 | { 2179 | title = locale("fuel_tank_title"), 2180 | icon = mods.modTank.icon or 'credit-card', 2181 | iconColor = getVehicleColor(), 2182 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modTank.modNum) > 0), 2183 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modTank.modNum)), 2184 | onSelect = function() 2185 | local vehicle = cache.vehicle 2186 | 2187 | local mod = mods.modTank.modNum 2188 | local mods = getVehicleModCounts(vehicle, mod) 2189 | 2190 | openModsMenu(vehicle, mod, mods) 2191 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2192 | end, 2193 | }, 2194 | { 2195 | title = locale("windows_title"), 2196 | icon = mods.modWindows.icon or 'credit-card', 2197 | iconColor = getVehicleColor(), 2198 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modWindows.modNum) > 0), 2199 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modWindows.modNum)), 2200 | onSelect = function() 2201 | local vehicle = cache.vehicle 2202 | 2203 | local mod = mods.modWindows.modNum 2204 | local mods = getVehicleModCounts(vehicle, mod) 2205 | 2206 | openModsMenu(vehicle, mod, mods) 2207 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2208 | end, 2209 | }, 2210 | { 2211 | title = locale("livery_title"), 2212 | icon = mods.modLivery.icon or 'credit-card', 2213 | iconColor = getVehicleColor(), 2214 | disabled = not (getVehicleModCounts(cache.vehicle, mods.modLivery.modNum) > 0), 2215 | description = tostring(getVehicleModCounts(cache.vehicle, mods.modLivery.modNum)), 2216 | onSelect = function() 2217 | local vehicle = cache.vehicle 2218 | 2219 | local mod = mods.modLivery.modNum 2220 | local mods = getVehicleModCounts(vehicle, mod) 2221 | 2222 | openModsMenu(vehicle, mod, mods) 2223 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2224 | end, 2225 | }, 2226 | } 2227 | }) 2228 | 2229 | lib.showContext('cosmeticsMenu') 2230 | end 2231 | 2232 | function openTuningMenu() 2233 | lib.hideTextUI() 2234 | lib.hideContext() 2235 | 2236 | local vehicle = cache.vehicle 2237 | modifiyingvehicle = vehicle 2238 | 2239 | FreezeEntityPosition(modifiyingvehicle, true) 2240 | 2241 | lib.registerContext({ 2242 | id = 'tuningMenu', 2243 | title = locale("tuning_menu_title"), 2244 | onExit = onExit, 2245 | options = { 2246 | { 2247 | title = locale("cosmetics_title"), 2248 | description = locale("description_cosmetics"), 2249 | icon = 'door-open', 2250 | onSelect = function() 2251 | openEstethicsMenu() 2252 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2253 | end, 2254 | }, 2255 | { 2256 | title = locale("upgrade_category_title"), 2257 | description = locale("description_upgrades"), 2258 | icon = 'wrench', 2259 | onSelect = function() 2260 | openUpgradeMenu() 2261 | playSound('SELECT', 'HUD_FREEMODE_SOUNDSET') 2262 | end, 2263 | }, 2264 | } 2265 | }) 2266 | 2267 | -- Setting the player cam position 2268 | local vehPos = GetEntityCoords(vehicle) 2269 | local camPos = GetOffsetFromEntityInWorldCoords(vehicle, -4.0, 0.0, 2.5) 2270 | local headingToObject = GetHeadingFromVector_2d(vehPos.x - camPos.x, vehPos.y - camPos.y) 2271 | 2272 | cam = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA', camPos.x, camPos.y, camPos.z, -35.0, 0.0, 2273 | headingToObject, GetGameplayCamFov(), false, 2) 2274 | 2275 | 2276 | SetCamActive(cam, true) 2277 | RenderScriptCams(true, true, 600, true, true) 2278 | 2279 | lib.showContext('tuningMenu') 2280 | showVehicleStats() 2281 | end 2282 | 2283 | function onExit() 2284 | lib.hideTextUI() 2285 | confirmPayment() 2286 | 2287 | RenderScriptCams(false, true, 600, true, true) 2288 | DestroyCam(cam, true) 2289 | FreezeEntityPosition(modifiyingvehicle, false) 2290 | end 2291 | -------------------------------------------------------------------------------- /client/functions/payment.lua: -------------------------------------------------------------------------------- 1 | lib.locale() 2 | 3 | function confirmPayment() 4 | if not cart[1] then return end 5 | 6 | local cost = 0 7 | local modListMsg = "" 8 | 9 | for k, v in ipairs(cart) do 10 | local modPrice = tonumber(v.modPrice) 11 | cost = cost + modPrice 12 | modListMsg = modListMsg .. "- " .. v.modLabel .. " " .. v.modLevel .. " **" .. modPrice .. "$** \n" 13 | end 14 | 15 | local confirmation = lib.alertDialog({ 16 | header = 'Payment confirmation', 17 | content = modListMsg, 18 | centered = false, 19 | cancel = true 20 | }) 21 | 22 | if confirmation == "confirm" then 23 | local hasMoney = lib.callback.await('ars_tuning:hasMoney', false, cost) 24 | 25 | if not hasMoney then 26 | lib.setVehicleProperties(cache.vehicle, currentVehProperties.old) 27 | 28 | cart = {} 29 | 30 | showNotification(locale("no_money")) 31 | return 32 | end 33 | 34 | lib.setVehicleProperties(cache.vehicle, currentVehProperties.new) 35 | TriggerServerEvent("ars_tuning:payMods", cost, currentVehProperties.new) 36 | cart = {} 37 | return 38 | end 39 | 40 | lib.setVehicleProperties(cache.vehicle, currentVehProperties.old) 41 | cart = {} 42 | end 43 | -------------------------------------------------------------------------------- /client/functions/utils.lua: -------------------------------------------------------------------------------- 1 | local vehicles = require "client.vehicle.vehicles" 2 | function getVehicleProperties(veh) 3 | local vehicle = veh 4 | local vehicleProperties = lib.getVehicleProperties(vehicle) 5 | 6 | return vehicleProperties 7 | end 8 | 9 | function getVehicleModCounts(veh, mod) 10 | local vehicle = veh 11 | 12 | local modCounts = GetNumVehicleMods(vehicle, mod) 13 | 14 | return modCounts 15 | end 16 | 17 | function playSound(soundName, audioName, soundId) 18 | local soundId = soundId or -1 19 | PlaySoundFrontend(soundId, soundName, audioName, false) 20 | end 21 | 22 | function showNotification(msg) 23 | lib.notify({ 24 | title = 'Tuning', 25 | description = msg, 26 | type = 'info' 27 | }) 28 | end 29 | 30 | function getVehicleColor() 31 | local r = 175 32 | local g = 179 33 | local b = 178 34 | 35 | local vehicle = cache.vehicle 36 | local vehColor = getVehicleProperties(vehicle).color1 37 | 38 | if type(vehColor) == "table" then 39 | r = vehColor[1] 40 | g = vehColor[2] 41 | b = vehColor[3] 42 | end 43 | 44 | local bgColor = "rgba(" .. r .. ", " .. g .. ", " .. b .. ", 0.7)" 45 | 46 | return bgColor 47 | end 48 | 49 | function toggleCam() 50 | -- todo 51 | end 52 | 53 | function showVehicleStats() 54 | local vehicle = cache.vehicle 55 | 56 | local vehicleModel = GetEntityModel(vehicle) 57 | local acceleration = (GetVehicleModelAcceleration(vehicleModel) or 0.0) * 10 58 | local maxSpeed = (GetVehicleModelEstimatedMaxSpeed(vehicleModel) or 0.0) / 10 59 | local breaks = GetVehicleModelMaxBraking(vehicleModel) or 0.0 60 | local power = (acceleration + maxSpeed) / 2 61 | 62 | local messageToShow = 'ㅤㅤㅤㅤㅤ**STATISTICS**ㅤㅤㅤㅤㅤ \n Power: ' .. 63 | math.round(power) .. 64 | " \n Acceleration: " .. 65 | math.round(acceleration) .. " \n Max Speed: " .. math.round(maxSpeed) .. " \n Breaks: " .. math.round(breaks) 66 | 67 | lib.showTextUI(messageToShow, { 68 | position = "right-center", 69 | icon = 'car', 70 | style = { 71 | borderRadius = 5, 72 | backgroundColor = getVehicleColor(), 73 | color = "#fff", 74 | } 75 | }) 76 | end 77 | 78 | function getVehiclePrice(vehicle) 79 | local vehicleModel = GetEntityModel(vehicle) 80 | 81 | for k, v in pairs(vehicles) do 82 | if vehicleModel == GetHashKey(k) then 83 | ownedPrice = v.price 84 | break 85 | end 86 | Wait(1) 87 | end 88 | 89 | return tonumber(ownedPrice) 90 | end 91 | 92 | function getHornName(index) 93 | if index == 0 then 94 | return "Truck Horn" 95 | elseif index == 1 then 96 | return "Cop Horn" 97 | elseif index == 2 then 98 | return "Clown Horn" 99 | elseif index == 3 then 100 | return "Musical Horn 1" 101 | elseif index == 4 then 102 | return "Musical Horn 2" 103 | elseif index == 5 then 104 | return "Musical Horn 3" 105 | elseif index == 6 then 106 | return "Musical Horn 4" 107 | elseif index == 7 then 108 | return "Musical Horn 5" 109 | elseif index == 8 then 110 | return "Sad Trombone" 111 | elseif index == 9 then 112 | return "Classical Horn 1" 113 | elseif index == 10 then 114 | return "Classical Horn 2" 115 | elseif index == 11 then 116 | return "Classical Horn 3" 117 | elseif index == 12 then 118 | return "Classical Horn 4" 119 | elseif index == 13 then 120 | return "Classical Horn 5" 121 | elseif index == 14 then 122 | return "Classical Horn 6" 123 | elseif index == 15 then 124 | return "Classical Horn 7" 125 | elseif index == 16 then 126 | return "Scale - Do" 127 | elseif index == 17 then 128 | return "Scale - Re" 129 | elseif index == 18 then 130 | return "Scale - Mi" 131 | elseif index == 19 then 132 | return "Scale - Fa" 133 | elseif index == 20 then 134 | return "Scale - Sol" 135 | elseif index == 21 then 136 | return "Scale - La" 137 | elseif index == 22 then 138 | return "Scale - Ti" 139 | elseif index == 23 then 140 | return "Scale - Do" 141 | elseif index == 24 then 142 | return "Jazz Horn 1" 143 | elseif index == 25 then 144 | return "Jazz Horn 2" 145 | elseif index == 26 then 146 | return "Jazz Horn 3" 147 | elseif index == 27 then 148 | return "Jazz Horn Loop" 149 | elseif index == 28 then 150 | return "Star Spangled Banner 1" 151 | elseif index == 29 then 152 | return "Star Spangled Banner 2" 153 | elseif index == 30 then 154 | return "Star Spangled Banner 3" 155 | elseif index == 31 then 156 | return "Star Spangled Banner 4" 157 | elseif index == 32 then 158 | return "Classical Horn 8 Loop" 159 | elseif index == 33 then 160 | return "Classical Horn 9 Loop" 161 | elseif index == 34 then 162 | return "Classical Horn 10 Loop" 163 | elseif index == 35 then 164 | return "Classical Horn 8" 165 | elseif index == 36 then 166 | return "Classical Horn 9" 167 | elseif index == 37 then 168 | return "Classical Horn 10" 169 | elseif index == 38 then 170 | return "Funeral Loop" 171 | elseif index == 39 then 172 | return "Funeral" 173 | elseif index == 40 then 174 | return "Spooky Loop" 175 | elseif index == 41 then 176 | return "Spooky" 177 | elseif index == 42 then 178 | return "San Andreas Loop" 179 | elseif index == 43 then 180 | return "San Andreas" 181 | elseif index == 44 then 182 | return "Liberty City Loop" 183 | elseif index == 45 then 184 | return "Liberty City" 185 | elseif index == 46 then 186 | return "Festive 1 Loop" 187 | elseif index == 47 then 188 | return "Festive 1" 189 | elseif index == 48 then 190 | return "Festive 2 Loop" 191 | elseif index == 49 then 192 | return "Festive 2" 193 | elseif index == 50 then 194 | return "Festive 3 Loop" 195 | elseif index == 51 then 196 | return "Festive 3" 197 | else 198 | return "N/A" 199 | end 200 | end 201 | -------------------------------------------------------------------------------- /client/vehicle/colorList.lua: -------------------------------------------------------------------------------- 1 | -- https://pastebin.com/pwHci0xK 2 | local colors = { 3 | pearlescent = { 4 | { 5 | category = "black", 6 | color = "black", 7 | colors = { 8 | { index = 0, label = "black", iconColor = "#030303"}, 9 | { index = 1, label = "graphite", iconColor = "#251607 "}, 10 | { index = 2, label = "black_metallic", iconColor = "#131618"}, 11 | { index = 3, label = "caststeel", iconColor = "#3a3c40"}, 12 | { index = 11, label = "black_anth", iconColor = "#383e42"}, 13 | { index = 12, label = "matteblack", iconColor = "#28282B"}, 14 | { index = 15, label = "darknight", iconColor = "#23383f"}, 15 | { index = 16, label = "deepblack", iconColor = "#000000"}, 16 | { index = 21, label = "oil", iconColor = "#373A36"}, 17 | { index = 147, label = "carbon", iconColor = "#625D5D"} 18 | } 19 | }, 20 | { 21 | category = "white", 22 | color = "white", 23 | colors = { 24 | { index = 106, label = "vanilla", iconColor = "#F3E5AB"}, 25 | { index = 107, label = "creme", iconColor = "#FFFDD0"}, 26 | { index = 111, label = "white", iconColor = "#FFFFFF"}, 27 | { index = 112, label = "polarwhite", iconColor = "#E2E0D6"}, 28 | { index = 113, label = "beige", iconColor = "#f5f5dc"}, 29 | { index = 121, label = "mattewhite", iconColor = "#FFFFFF"}, 30 | { index = 122, label = "snow", iconColor = "#fffafa"}, 31 | { index = 131, label = "cotton", iconColor = "#bfad9d"}, 32 | { index = 132, label = "alabaster", iconColor = "#EDEADE"}, 33 | { index = 134, label = "purewhite", iconColor = "#FFFFFF"} 34 | } 35 | }, 36 | { 37 | category = "grey", 38 | color = "grey", 39 | colors = { 40 | { index = 4, label = "silver", iconColor = "#C0C0C0"}, 41 | { index = 5, label = "metallicgrey", iconColor = "#8D918D"}, 42 | { index = 6, label = "laminatedsteel", iconColor = "#948c7e"}, 43 | { index = 7, label = "darkgray", iconColor = "#5A5A5A"}, 44 | { index = 8, label = "rockygray", iconColor = "#5E6B6C"}, 45 | { index = 9, label = "graynight", iconColor = "#676767"}, 46 | { index = 10, label = "aluminum", iconColor = "#848789"}, 47 | { index = 13, label = "graymat", iconColor = "#7B7B7C"}, 48 | { index = 14, label = "lightgrey", iconColor = "#D3D3D3"}, 49 | { index = 17, label = "asphaltgray", iconColor = "#6F6E63"}, 50 | { index = 18, label = "grayconcrete", iconColor = "#808076"}, 51 | { index = 19, label = "darksilver", iconColor = "#71706E"}, 52 | { index = 20, label = "magnesite", iconColor = "#5d7a78"}, 53 | { index = 22, label = "nickel", iconColor = "#727472"}, 54 | { index = 23, label = "zinc", iconColor = "#bac4c8"}, 55 | { index = 24, label = "dolomite", iconColor = "#444953"}, 56 | { index = 25, label = "bluesilver", iconColor = "#5f6c81"}, 57 | { index = 26, label = "titanium", iconColor = "#878681"}, 58 | { index = 66, label = "steelblue", iconColor = "#4682b4"}, 59 | { index = 93, label = "champagne", iconColor = "#F7E7CE"}, 60 | { index = 144, label = "grayhunter", iconColor = "#808080"}, 61 | { index = 156, label = "grey", iconColor = "#808080"} 62 | } 63 | }, 64 | { 65 | category = "red", 66 | color = "red", 67 | colors = { 68 | { index = 27, label = "red", iconColor = "#FF0000"}, 69 | { index = 28, label = "torino_red", iconColor = "#bf0010"}, 70 | { index = 29, label = "poppy", iconColor = "#E35335"}, 71 | { index = 30, label = "copper_red", iconColor = "#cb6d51"}, 72 | { index = 31, label = "cardinal", iconColor = "#C41E3A"}, 73 | { index = 32, label = "brick", iconColor = "#AA4A44"}, 74 | { index = 33, label = "garnet", iconColor = "#9A2A2A"}, 75 | { index = 34, label = "cabernet", iconColor = "#280008"}, 76 | { index = 35, label = "candy", iconColor = "#ffbcd9"}, 77 | { index = 39, label = "matte_red", iconColor = "#FF0000"}, 78 | { index = 40, label = "dark_red", iconColor = "#8B0000"}, 79 | { index = 43, label = "red_pulp", iconColor = "#c70000"}, 80 | { index = 44, label = "bril_red", iconColor = "#c70000"}, 81 | { index = 46, label = "pale_red", iconColor = "#D9544D"}, 82 | { index = 143, label = "wine_red", iconColor = "#b11226"}, 83 | { index = 150, label = "volcano", iconColor = "#4E2728"} 84 | } 85 | }, 86 | { 87 | category = "pink", 88 | color = "pink", 89 | colors = { 90 | { index = 135, label = "electricpink", iconColor = "#f62681"}, 91 | { index = 136, label = "salmon", iconColor = "#FA8072"}, 92 | { index = 137, label = "sugarplum", iconColor = "#914E75"} 93 | } 94 | }, 95 | { 96 | category = "blue", 97 | color = "blue", 98 | colors = { 99 | { index = 54, label = "topaz", iconColor = "#426f7e"}, 100 | { index = 60, label = "light_blue", iconColor = "#ADD8E6"}, 101 | { index = 61, label = "galaxy_blue", iconColor = "#394361"}, 102 | { index = 62, label = "dark_blue", iconColor = "#00008B"}, 103 | { index = 63, label = "azure", iconColor = "#007fff"}, 104 | { index = 64, label = "navy_blue", iconColor = "#000080"}, 105 | { index = 65, label = "lapis", iconColor = "#26619c"}, 106 | { index = 67, label = "blue_diamond", iconColor = "#4EE2EC"}, 107 | { index = 68, label = "surfer", iconColor = "#01a4a5"}, 108 | { index = 69, label = "pastel_blue", iconColor = "#AEC6CF"}, 109 | { index = 70, label = "celeste_blue", iconColor = "#b2ffff"}, 110 | { index = 73, label = "rally_blue", iconColor = "#0e4bef"}, 111 | { index = 74, label = "blue_paradise", iconColor = "#5484AA"}, 112 | { index = 75, label = "blue_night", iconColor = "#074355"}, 113 | { index = 77, label = "cyan_blue", iconColor = "#00FFFF"}, 114 | { index = 78, label = "cobalt", iconColor = "#0047AB"}, 115 | { index = 79, label = "electric_blue", iconColor = "#7DF9FF"}, 116 | { index = 80, label = "horizon_blue", iconColor = "#86B3D1"}, 117 | { index = 82, label = "metallic_blue", iconColor = "#32527B"}, 118 | { index = 83, label = "aquamarine", iconColor = "#7FFFD4"}, 119 | { index = 84, label = "blue_agathe", iconColor = "#B5E1E9"}, 120 | { index = 85, label = "zirconium", iconColor = "#57FEFF"}, 121 | { index = 86, label = "spinel", iconColor = "#995763"}, 122 | { index = 87, label = "tourmaline", iconColor = "#92C1C0"}, 123 | { index = 127, label = "paradise", iconColor = "#BED3DE"}, 124 | { index = 140, label = "bubble_gum", iconColor = "#ffc1cc"}, 125 | { index = 141, label = "midnight_blue", iconColor = "#191970"}, 126 | { index = 146, label = "forbidden_blue", iconColor = "#191970"}, 127 | { index = 157, label = "glacier_blue", iconColor = "#729DC8"} 128 | } 129 | }, 130 | { 131 | category = "yellow", 132 | color = "yellow", 133 | colors = { 134 | { index = 42, label = "yellow", iconColor = "#FFFF00"}, 135 | { index = 88, label = "wheat", iconColor = "#F5DEB3"}, 136 | { index = 89, label = "raceyellow", iconColor = "#f5d365 "}, 137 | { index = 91, label = "paleyellow", iconColor = "#FDFD96"}, 138 | { index = 126, label = "lightyellow", iconColor = "#ffffe0"} 139 | } 140 | }, 141 | { 142 | category = "green", 143 | color = "green", 144 | colors = { 145 | { index = 49, label = "met_dark_green", iconColor = "#013220"}, 146 | { index = 50, label = "rally_green", iconColor = "#7ec083 "}, 147 | { index = 51, label = "pine_green", iconColor = "#01796f"}, 148 | { index = 52, label = "olive_green", iconColor = "#808000"}, 149 | { index = 53, label = "light_green", iconColor = "#6aab8e"}, 150 | { index = 55, label = "lime_green", iconColor = "#32cd32"}, 151 | { index = 56, label = "forest_green", iconColor = "#228b22"}, 152 | { index = 57, label = "lawn_green", iconColor = "#7CFC00"}, 153 | { index = 58, label = "imperial_green", iconColor = "#081b1a"}, 154 | { index = 59, label = "green_bottle", iconColor = "#051F19"}, 155 | { index = 92, label = "citrus_green", iconColor = "#96D406"}, 156 | { index = 125, label = "green_anis", iconColor = "#BEC8B9"}, 157 | { index = 128, label = "khaki", iconColor = "#728639"}, 158 | { index = 133, label = "army_green", iconColor = "#4b5320"}, 159 | { index = 151, label = "dark_green", iconColor = "#013220"}, 160 | { index = 152, label = "hunter_green", iconColor = "#355E3B"}, 161 | { index = 155, label = "matte_foilage_green", iconColor = "#7e8772"} 162 | } 163 | }, 164 | { 165 | category = "orange", 166 | color = "orange", 167 | colors = { 168 | { index = 36, label = "tangerine", iconColor = "#F28500"}, 169 | { index = 38, label = "orange", iconColor = "#FFA500"}, 170 | { index = 41, label = "matteorange", iconColor = "#FFA500"}, 171 | { index = 123, label = "lightorange", iconColor = "#FFD580"}, 172 | { index = 124, label = "peach", iconColor = "#FFE5B4"}, 173 | { index = 130, label = "pumpkin", iconColor = "#FF7518"}, 174 | { index = 138, label = "orangelambo", iconColor = "#e46400"} 175 | } 176 | }, 177 | { 178 | category = "brown", 179 | color = "brown", 180 | colors = { 181 | { index = 45, label = "copper", iconColor = "#b87333"}, 182 | { index = 47, label = "lightbrown", iconColor = "#C4A484"}, 183 | { index = 48, label = "darkbrown", iconColor = "#5C4033"}, 184 | { index = 90, label = "bronze", iconColor = "#CD7F32"}, 185 | { index = 94, label = "brownmetallic", iconColor = "#ac4313"}, 186 | { index = 95, label = "expresso", iconColor = "#4E2A2A"}, 187 | { index = 96, label = "chocolate", iconColor = "#7B3F00"}, 188 | { index = 97, label = "terracotta", iconColor = "#E2725B"}, 189 | { index = 98, label = "marble", iconColor = "#566D7E"}, 190 | { index = 99, label = "sand", iconColor = "#C2B280"}, 191 | { index = 100, label = "sepia", iconColor = "#704214"}, 192 | { index = 101, label = "bison", iconColor = "#003A63"}, 193 | { index = 102, label = "palm", iconColor = "#6f9940"}, 194 | { index = 103, label = "caramel", iconColor = "#85461e"}, 195 | { index = 104, label = "rust", iconColor = "#B7410E"}, 196 | { index = 105, label = "chestnut", iconColor = "#954535"}, 197 | { index = 108, label = "brown", iconColor = "#964B00"}, 198 | { index = 109, label = "hazelnut", iconColor = "#ae9f80"}, 199 | { index = 110, label = "shell", iconColor = "#fbce07"}, 200 | { index = 114, label = "mahogany", iconColor = "#C04000"}, 201 | { index = 115, label = "cauldron", iconColor = "#5f4e48"}, 202 | { index = 116, label = "blond", iconColor = "#faf0be"}, 203 | { index = 129, label = "gravel", iconColor = "#53544E"}, 204 | { index = 153, label = "darkearth", iconColor = "#786c5e"}, 205 | { index = 154, label = "desert", iconColor = "#FAD5A5"} 206 | } 207 | }, 208 | { 209 | category = "purple", 210 | color = "purple", 211 | colors = { 212 | { index = 71, label = "indigo", iconColor = "#4B0082"}, 213 | { index = 72, label = "deeppurple", iconColor = "#36013F"}, 214 | { index = 76, label = "darkviolet", iconColor = "#9400d3"}, 215 | { index = 81, label = "amethyst", iconColor = "#9966cc"}, 216 | { index = 142, label = "mysticalviolet", iconColor = "#9f97b1"}, 217 | { index = 145, label = "purplemetallic", iconColor = "#5b0a91"}, 218 | { index = 148, label = "matteviolet", iconColor = "#E3D9E1"}, 219 | { index = 149, label = "mattedeeppurple", iconColor = "#5F396A"} 220 | } 221 | }, 222 | { 223 | category = "chrome", 224 | color = "chrome", 225 | colors = { 226 | { index = 117, label = "brushedchrome", iconColor = "#E8E3DA"}, 227 | { index = 118, label = "blackchrome", iconColor = "#626569"}, 228 | { index = 119, label = "brushedaluminum", iconColor = "#E6EDf5"}, 229 | { index = 120, label = "chrome", iconColor = "#dbe4eb"} 230 | } 231 | }, 232 | { 233 | category = "gold", 234 | color = "gold", 235 | colors = { 236 | { index = 37, label = "gold", iconColor = "#FFD700"}, 237 | { index = 158, label = "puregold", iconColor = "#d3ad7e"}, 238 | { index = 159, label = "brushedgold", iconColor = "#FFD700"}, 239 | { index = 160, label = "lightgold", iconColor = "#FDDC5C"} 240 | } 241 | } 242 | }, 243 | xenon = { 244 | {label = "white", index = 0}, iconColor = "#FFFFFF", 245 | {label = "blue", index = 1, iconColor = "#0000FF"}, 246 | {label = "electric_blue", index = 2, iconColor = "#7DF9FF"}, 247 | {label = "mintgreen", index = 3, iconColor = "#3EB489"}, 248 | {label = "lime_green", index = 4, iconColor = "#32CD32"}, 249 | {label = "yellow", index = 5, iconColor = "#FFFF00"}, 250 | {label = "goldenshower", index = 6, iconColor = "#FFBB34"}, 251 | {label = "orange", index = 7, iconColor = "#FFA500"}, 252 | {label = "red", index = 8, iconColor = "#FF0000"}, 253 | {label = "ponypink", index = 9, iconColor = "#EFCFE2"}, 254 | {label = "hotpink", index = 10, iconColor = "#FF69B4"}, 255 | {label = "purple", index = 11, iconColor = "#A020F0"}, 256 | {label = "blacklight", index = 12, iconColor = "#cb3562"}, 257 | {label = "default", index = -1, iconColor = "#FFFF33"}, 258 | } 259 | } 260 | 261 | 262 | return colors 263 | -------------------------------------------------------------------------------- /client/vehicle/modList.lua: -------------------------------------------------------------------------------- 1 | local mods = { 2 | modEngine = { 3 | modNum = 11, 4 | label = "Engine Level", 5 | parent = "upgradeMenu", 6 | title = "Engine", 7 | icon = "gauge", 8 | price = { 13.95, 32.56, 65.12, 139.53 } 9 | }, 10 | modBrakes = { 11 | modNum = 12, 12 | label = "Brakes Level", 13 | parent = "upgradeMenu", 14 | title = "Breaks", 15 | price = { 4.65, 9.3, 18.6, 13.95 } 16 | }, 17 | modTransmission = { 18 | modNum = 13, 19 | label = "Transimission Level", 20 | parent = "upgradeMenu", 21 | title = "Transmission", 22 | price = { 13.95, 20.93, 46.51, 63.55 } 23 | }, 24 | modSuspension = { 25 | modNum = 15, 26 | label = "Suspension Level", 27 | parent = "upgradeMenu", 28 | title = "Suspension", 29 | price = { 3.72, 7.44, 14.88, 29.77, 40.2 } 30 | }, 31 | modArmor = { 32 | modNum = 16, 33 | label = "Armor Level", 34 | parent = "upgradeMenu", 35 | title = "Armor", 36 | price = { 69.77, 116.28, 130.00, 150.00, 180.00, 190.00 } 37 | }, 38 | modTurbo = { 39 | modNum = 18, 40 | label = "Trubo", 41 | parent = "upgradeMenu", 42 | title = "Turbo", 43 | price = 55.81 44 | }, 45 | --- body parts 46 | modSpoilers = { 47 | modNum = 0, 48 | label = "Spoiler", 49 | parent = "bodyPartsMenu", 50 | title = "Spoilers", 51 | icon = "wind", 52 | price = 4.65 53 | }, 54 | modFrontBumper = { 55 | modNum = 1, 56 | label = "Front Bumper", 57 | parent = "bodyPartsMenu", 58 | title = "Front Bumpers", 59 | icon = "car-rear", 60 | price = 5.12 61 | }, 62 | modRearBumper = { 63 | modNum = 2, 64 | label = "Rear Bumper", 65 | parent = "bodyPartsMenu", 66 | title = "Rear Bumpers", 67 | icon = "car-rear", 68 | price = 5.12 69 | }, 70 | modSideSkirt = { 71 | modNum = 3, 72 | label = "Side Skirt", 73 | parent = "bodyPartsMenu", 74 | title = "Side Skirt", 75 | icon = "car-side", 76 | price = 4.65 77 | }, 78 | modExhaust = { 79 | modNum = 4, 80 | label = "Exhaust", 81 | parent = "bodyPartsMenu", 82 | title = "Exhaust", 83 | icon = "car", 84 | price = 5.12 85 | }, 86 | modFrame = { 87 | modNum = 5, 88 | label = "Frame", 89 | parent = "bodyPartsMenu", 90 | title = "Frame", 91 | icon = "car", 92 | price = 5.12 93 | }, 94 | modGrille = { 95 | modNum = 6, 96 | label = "Grille", 97 | parent = "bodyPartsMenu", 98 | title = "Grille", 99 | icon = "car", 100 | price = 3.72 101 | }, 102 | modHood = { 103 | modNum = 7, 104 | label = "Hood", 105 | parent = "bodyPartsMenu", 106 | title = "Hood", 107 | icon = "car", 108 | price = 4.88 109 | }, 110 | modFender = { 111 | modNum = 8, 112 | label = "Left Fender", 113 | parent = "bodyPartsMenu", 114 | title = "Left Fender", 115 | icon = "car-side", 116 | price = 5.12 117 | }, 118 | modRightFender = { 119 | modNum = 9, 120 | label = "Right Fender", 121 | parent = "bodyPartsMenu", 122 | title = "Right Fender", 123 | icon = "car-side", 124 | price = 5.12 125 | }, 126 | modRoof = { 127 | modNum = 10, 128 | label = "Roof", 129 | parent = "bodyPartsMenu", 130 | title = "Roof", 131 | icon = "car", 132 | price = 5.58 133 | }, 134 | modHorns = { 135 | modNum = 14, 136 | label = "Horn", 137 | parent = "cosmeticsMenu", 138 | title = "Horn", 139 | icon = "bullhorn", 140 | price = 1.12 141 | }, 142 | modXenon = { 143 | modNum = 22, 144 | label = "Xenon", 145 | parent = 'bodyPartsMenu', 146 | title = "Xenon", 147 | icon = "lightbulb", 148 | price = 1.12 149 | }, 150 | modFrontWheel0 = { 151 | label = "sport", 152 | parent = 'wheelsMenu', 153 | modNum = 23, 154 | title = "Sport", 155 | icon = "dharmachakra", 156 | price = 4.65 157 | 158 | }, 159 | modFrontWheel1 = { 160 | label = "muscle", 161 | parent = 'wheelsMenu', 162 | modNum = 23, 163 | title = "Muscle", 164 | icon = "dharmachakra", 165 | price = 4.65 166 | }, 167 | modFrontWheel2 = { 168 | label = "lowrider", 169 | parent = 'wheelsMenu', 170 | modNum = 23, 171 | title = "Lowrider", 172 | icon = "dharmachakra", 173 | price = 4.65 174 | }, 175 | modFrontWheel3 = { 176 | label = "suv", 177 | parent = 'wheelsMenu', 178 | modNum = 23, 179 | title = "Suv", 180 | icon = "dharmachakra", 181 | price = 4.65 182 | }, 183 | modFrontWheel4 = { 184 | label = "allterrain", 185 | parent = 'wheelsMenu', 186 | modNum = 23, 187 | title = "Allterrain", 188 | icon = "dharmachakra", 189 | price = 4.65 190 | }, 191 | modFrontWheel5 = { 192 | label = "tuning", 193 | parent = 'wheelsMenu', 194 | modNum = 23, 195 | title = "Tuning", 196 | icon = "dharmachakra", 197 | price = 4.65 198 | }, 199 | modFrontWheel6 = { 200 | label = "motorcycle", 201 | parent = 'wheelsMenu', 202 | modNum = 23, 203 | title = "Motorcycle", 204 | icon = "dharmachakra", 205 | price = 4.65 206 | }, 207 | modFrontWheel7 = { 208 | label = "highend", 209 | parent = 'wheelsMenu', 210 | modNum = 23, 211 | title = "Highend", 212 | icon = "dharmachakra", 213 | price = 4.65 214 | }, 215 | modPlateHolder = { 216 | modNum = 25, 217 | label = "Plate holder", 218 | parent = 'cosmeticsMenu', 219 | title = "Plate Holders", 220 | icon = "credit-card", 221 | price = 3.49 222 | }, 223 | modVanityPlate = { 224 | modNum = 26, 225 | label = "Vanity Plate", 226 | parent = 'cosmeticsMenu', 227 | title = "Vanity Plates", 228 | icon = "credit-card", 229 | price = 1.1 230 | }, 231 | modTrimA = { 232 | modNum = 27, 233 | label = "Interior", 234 | parent = 'cosmeticsMenu', 235 | title = "Interior", 236 | icon = "couch", 237 | price = 6.98 238 | }, 239 | modOrnaments = { 240 | modNum = 28, 241 | label = "Trim", 242 | parent = 'cosmeticsMenu', 243 | title = "Trim", 244 | icon = "t", 245 | price = 0.9 246 | }, 247 | modDashboard = { 248 | modNum = 29, 249 | label = "Dashboard", 250 | parent = 'cosmeticsMenu', 251 | title = "Dashboard", 252 | icon = "car", 253 | price = 4.65 254 | }, 255 | modDial = { 256 | modNum = 30, 257 | label = "Speedometer", 258 | parent = 'cosmeticsMenu', 259 | title = "Speedometer", 260 | icon = "gauge", 261 | price = 4.19 262 | }, 263 | modDoorSpeaker = { 264 | modNum = 31, 265 | label = "Door Speaker", 266 | parent = 'cosmeticsMenu', 267 | title = "Door Speaker", 268 | icon = "door-open", 269 | price = 5.58 270 | }, 271 | modSeats = { 272 | modNum = 32, 273 | label = "Seats", 274 | parent = 'cosmeticsMenu', 275 | title = "Seat", 276 | icon = "chair", 277 | price = 4.65 278 | }, 279 | modSteeringWheel = { 280 | modNum = 33, 281 | label = "Steering wheel", 282 | parent = 'cosmeticsMenu', 283 | title = "Steering wheel", 284 | icon = "dharmachakra", 285 | price = 4.19 286 | }, 287 | modShifterLeavers = { 288 | modNum = 34, 289 | label = "Shifter Leavers", 290 | parent = 'cosmeticsMenu', 291 | title = "Shifter leavers", 292 | icon = "gear", 293 | price = 3.26 294 | }, 295 | modAPlate = { 296 | modNum = 35, 297 | label = "Plate", 298 | parent = 'cosmeticsMenu', 299 | title = "Plate", 300 | icon = "credit-card", 301 | price = 4.19 302 | }, 303 | modSpeakers = { 304 | modNum = 36, 305 | label = "Speakers", 306 | parent = 'cosmeticsMenu', 307 | title = "Speakers", 308 | icon = "headphones", 309 | price = 6.98 310 | }, 311 | modTrunk = { 312 | modNum = 37, 313 | label = "Trunk", 314 | parent = 'cosmeticsMenu', 315 | title = "Trunk", 316 | icon = "car-rear", 317 | price = 5.58 318 | }, 319 | modHydrolic = { 320 | modNum = 38, 321 | label = "Hydrolic", 322 | parent = 'cosmeticsMenu', 323 | title = "Hydrolic", 324 | icon = "h", 325 | price = 5.12 326 | }, 327 | modEngineBlock = { 328 | modNum = 39, 329 | label = "Engine block", 330 | parent = 'cosmeticsMenu', 331 | title = "Engine block", 332 | icon = "battery-empty", 333 | price = 5.12 334 | }, 335 | modAirFilter = { 336 | modNum = 40, 337 | label = "Air filter", 338 | parent = 'cosmeticsMenu', 339 | title = "Air filter", 340 | icon = "filter", 341 | price = 3.72 342 | }, 343 | modStruts = { 344 | modNum = 41, 345 | label = "Struts", 346 | parent = 'cosmeticsMenu', 347 | title = "Struts", 348 | icon = "gear", 349 | price = 6.51 350 | }, 351 | modArchCover = { 352 | modNum = 42, 353 | label = "Arch Cover", 354 | parent = 'cosmeticsMenu', 355 | title = "Arch Cover", 356 | icon = "bezier-curve", 357 | price = 4.19 358 | }, 359 | modAerials = { 360 | modNum = 43, 361 | label = "Aerials", 362 | parent = 'cosmeticsMenu', 363 | title = "Aerials", 364 | icon = "signal", 365 | price = 1.12 366 | }, 367 | modTrimB = { 368 | modNum = 44, 369 | label = "Wings", 370 | parent = 'cosmeticsMenu', 371 | title = "Wings", 372 | icon = "cloud", 373 | price = 6.05 374 | }, 375 | modTank = { 376 | modNum = 45, 377 | label = "Tank", 378 | parent = 'cosmeticsMenu', 379 | title = "Tank", 380 | icon = "gas-pump", 381 | price = 4.19 382 | }, 383 | modWindows = { 384 | modNum = 46, 385 | label = "Windows", 386 | parent = 'cosmeticsMenu', 387 | title = "Windows", 388 | icon = "window-maximize", 389 | price = 4.19 390 | }, 391 | modLivery = { 392 | modNum = 48, 393 | label = "Livery", 394 | parent = 'cosmeticsMenu', 395 | title = "Livery", 396 | icon = "spray-can-sparkles", 397 | price = 9.3 398 | }, 399 | 400 | plateIndex = { 401 | modNum = "plateIndex", 402 | label = "plate", 403 | parent = 'bodyPartsMenu', 404 | title = "Plate", 405 | icon = "credit-card", 406 | price = 1.1 407 | }, 408 | color = { 409 | icon = "droplet", 410 | price = 1.2 411 | }, 412 | windowTint = { 413 | icon = "paint-roller", 414 | price = 1.2 415 | }, 416 | neon = { 417 | icon = "paint-roller", 418 | price = 1.2 419 | }, 420 | wheelsColor = { 421 | price = 1.2, 422 | } 423 | } 424 | 425 | 426 | return mods 427 | -------------------------------------------------------------------------------- /client/vehicle/vehicles.lua: -------------------------------------------------------------------------------- 1 | local vehicles = { 2 | ['adder'] = { 3 | name = 'Adder', 4 | price = '765000' 5 | }, 6 | ['akuma'] = { 7 | name = 'Akuma', 8 | price = '22000' 9 | }, 10 | ['alpha'] = { 11 | name = 'Alpha', 12 | price = '32000' 13 | }, 14 | ['aqv'] = { 15 | name = 'Alpha romeo giulia', 16 | price = '413000' 17 | }, 18 | ['avarus'] = { 19 | name = 'Avarus', 20 | price = '19000' 21 | }, 22 | ['bagger'] = { 23 | name = 'Bagger', 24 | price = '7000' 25 | }, 26 | ['baller2'] = { 27 | name = 'Baller', 28 | price = '65000' 29 | }, 30 | ['baller3'] = { 31 | name = 'Baller Sport', 32 | price = '70000' 33 | }, 34 | ['bati'] = { 35 | name = 'Bati 801', 36 | price = '22000' 37 | }, 38 | ['bati2'] = { 39 | name = 'Bati 801RR', 40 | price = '23000' 41 | }, 42 | ['bf400'] = { 43 | name = 'BF400', 44 | price = '35000' 45 | }, 46 | ['bifta'] = { 47 | name = 'Bifta', 48 | price = '17000' 49 | }, 50 | ['bison'] = { 51 | name = 'Bison', 52 | price = '45000' 53 | }, 54 | ['blade'] = { 55 | name = 'Blade', 56 | price = '15000' 57 | }, 58 | ['blazer'] = { 59 | name = 'Blazer', 60 | price = '6500' 61 | }, 62 | ['blazer4'] = { 63 | name = 'Blazer Sport', 64 | price = '8500' 65 | }, 66 | ['blazer5'] = { 67 | name = 'Blazer 5', 68 | price = '1755600' 69 | }, 70 | ['blista'] = { 71 | name = 'Blista', 72 | price = '8000' 73 | }, 74 | ['bmci'] = { 75 | name = 'BMW M5', 76 | price = '465000' 77 | }, 78 | ['brawler'] = { 79 | name = 'Brawler', 80 | price = '45000' 81 | }, 82 | ['brioso'] = { 83 | name = 'Brioso R/A', 84 | price = '18000' 85 | }, 86 | ['burrito3'] = { 87 | name = 'Burrito', 88 | price = '19000' 89 | }, 90 | ['carbonrs'] = { 91 | name = 'Carbon RS', 92 | price = '32000' 93 | }, 94 | ['cheetah'] = { 95 | name = 'Cheetah', 96 | price = '375000' 97 | }, 98 | ['chimera'] = { 99 | name = 'Chimera', 100 | price = '17000' 101 | }, 102 | ['cognoscenti'] = { 103 | name = 'Cognoscenti', 104 | price = '55000' 105 | }, 106 | ['contender'] = { 107 | name = 'Contender', 108 | price = '70000' 109 | }, 110 | ['dominator'] = { 111 | name = 'Dominator', 112 | price = '54500' 113 | }, 114 | ['dubsta2'] = { 115 | name = 'Dubsta Luxuary', 116 | price = '60000' 117 | }, 118 | ['dubsta3'] = { 119 | name = 'Bubsta 6x6', 120 | price = '120000' 121 | }, 122 | ['elegy2'] = { 123 | name = 'Elegy', 124 | price = '38500' 125 | }, 126 | ['entityxf'] = { 127 | name = 'Entity XF', 128 | price = '425000' 129 | }, 130 | ['exemplar'] = { 131 | name = 'Exemplar', 132 | price = '32000' 133 | }, 134 | ['f620'] = { 135 | name = 'F620', 136 | price = '40000' 137 | }, 138 | ['faggio'] = { 139 | name = 'Faggio', 140 | price = '4000' 141 | }, 142 | ['felon'] = { 143 | name = 'Felon', 144 | price = '42000' 145 | }, 146 | ['felon2'] = { 147 | name = 'Felon GT', 148 | price = '55000' 149 | }, 150 | ['fmj'] = { 151 | name = 'FMJ', 152 | price = '440000' 153 | }, 154 | ['furoregt'] = { 155 | name = 'Furore GT', 156 | price = '85000' 157 | }, 158 | ['fusilade'] = { 159 | name = 'Fusilade', 160 | price = '50000' 161 | }, 162 | ['guardian'] = { 163 | name = 'Guardian', 164 | price = '45000' 165 | }, 166 | ['hustler'] = { 167 | name = 'Hustler', 168 | price = '625000' 169 | }, 170 | ['infernus'] = { 171 | name = 'Infernus', 172 | price = '380000' 173 | }, 174 | ['issi2'] = { 175 | name = 'Issi', 176 | price = '10000' 177 | }, 178 | ['jackal'] = { 179 | name = 'Jackal', 180 | price = '38000' 181 | }, 182 | ['kamacho'] = { 183 | name = 'Kamacho', 184 | price = '175000' 185 | }, 186 | ['khamelion'] = { 187 | name = 'Khamelion', 188 | price = '38000' 189 | }, 190 | ['kuruma'] = { 191 | name = 'Kuruma', 192 | price = '90000' 193 | }, 194 | ['landstalker'] = { 195 | name = 'Landstalker', 196 | price = '35000' 197 | }, 198 | ['le7b'] = { 199 | name = 'RE-7B', 200 | price = '325000' 201 | }, 202 | ['lynx'] = { 203 | name = 'Lynx', 204 | price = '40000' 205 | }, 206 | ['mamba'] = { 207 | name = 'Mamba', 208 | price = '70000' 209 | }, 210 | ['manana'] = { 211 | name = 'Manana', 212 | price = '12800' 213 | }, 214 | ['massacro'] = { 215 | name = 'Massacro', 216 | price = '65000' 217 | }, 218 | ['massacro2'] = { 219 | name = 'Massacro(Racecar)', 220 | price = '130000' 221 | }, 222 | ['mesa3'] = { 223 | name = 'Mesa', 224 | price = '85000' 225 | }, 226 | ['monster'] = { 227 | name = 'The Liberator', 228 | price = '210000' 229 | }, 230 | ['neon'] = { 231 | name = 'Neon', 232 | price = '450000' 233 | }, 234 | ['nightblade'] = { 235 | name = 'Nightblade', 236 | price = '35000' 237 | }, 238 | ['nightshade'] = { 239 | name = 'Nightshade', 240 | price = '65000' 241 | }, 242 | ['omnis'] = { 243 | name = 'Omnis', 244 | price = '35000' 245 | }, 246 | ['oracle2'] = { 247 | name = 'Oracle XS', 248 | price = '35000' 249 | }, 250 | ['panto'] = { 251 | name = 'Panto', 252 | price = '10000' 253 | }, 254 | ['pariah'] = { 255 | name = 'Pariah', 256 | price = '235000' 257 | }, 258 | ['prototipo'] = { 259 | name = 'X80 Proto', 260 | price = '65000' 261 | }, 262 | ['raptor150'] = { 263 | name = 'Raptor', 264 | price = '380000' 265 | }, 266 | ['reaper'] = { 267 | name = 'Reaper', 268 | price = '230000' 269 | }, 270 | ['riata'] = { 271 | name = 'Riata', 272 | price = '380000' 273 | }, 274 | ['rumpo'] = { 275 | name = 'Rumpo', 276 | price = '27000' 277 | }, 278 | ['rumpo3'] = { 279 | name = 'Rumpo Trail', 280 | price = '68124' 281 | }, 282 | ['sanchez'] = { 283 | name = 'Sanchez', 284 | price = '22000' 285 | }, 286 | ['sanctus'] = { 287 | name = 'Sanctus', 288 | price = '25000' 289 | }, 290 | ['sandking'] = { 291 | name = 'Sandking', 292 | price = '55000' 293 | }, 294 | ['sc1'] = { 295 | name = 'SC 1', 296 | price = '329000' 297 | }, 298 | ['senna'] = { 299 | name = 'Senna', 300 | price = '857000' 301 | }, 302 | ['seven70'] = { 303 | name = 'Seven 70', 304 | price = '39500' 305 | }, 306 | ['sheava'] = { 307 | name = 'ETR1', 308 | price = '220000' 309 | }, 310 | ['Sultan RS'] = { 311 | name = 'sultanrs', 312 | price = '65000' 313 | }, 314 | ['t20'] = { 315 | name = 'T 20', 316 | price = '420000' 317 | }, 318 | ['tempesta'] = { 319 | name = 'Tempesta', 320 | price = '350000' 321 | }, 322 | ['tropos'] = { 323 | name = 'Tropos', 324 | price = '40000' 325 | }, 326 | ['coquette'] = { 327 | name = 'Coquette', 328 | price = '65000' 329 | }, 330 | ['turismor'] = { 331 | name = 'Turismo R', 332 | price = '220000' 333 | }, 334 | ['vacca'] = { 335 | name = 'Vacca', 336 | price = '170000' 337 | }, 338 | ['verlierer2'] = { 339 | name = 'Verlierer', 340 | price = '70000' 341 | }, 342 | ['visione'] = { 343 | name = 'Visione', 344 | price = '780000' 345 | }, 346 | ['voltic'] = { 347 | name = 'Voltic', 348 | price = '90000' 349 | }, 350 | ['voodoo'] = { 351 | name = 'Voodoo', 352 | price = '21000' 353 | }, 354 | ['vortex'] = { 355 | name = 'Vortex', 356 | price = '9800' 357 | }, 358 | ['windsor'] = { 359 | name = 'Windsor', 360 | price = '95000' 361 | }, 362 | ['windsor2'] = { 363 | name = 'Windsor Drop', 364 | price = '125000' 365 | }, 366 | ['zentorno'] = { 367 | name = 'zentorno', 368 | price = '700000' 369 | }, 370 | } 371 | 372 | 373 | return vehicles 374 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | 3 | Config.WorkShops = { 4 | { 5 | job = "mechanic", -- false if you dont want to use the job 6 | pos = vector3(-211.4554, -1323.0739, 30.8904), 7 | blip = { 8 | enable = true, 9 | name = "Bennys Tuning", 10 | type = 566, 11 | scale = 0.8, 12 | color = 5, 13 | }, 14 | }, 15 | -- { 16 | -- job = false, -- false if you dont want to use the job 17 | -- pos = vector3(-211.4554, -1323.0739, 30.8904), 18 | -- blip = { 19 | -- enable = true, 20 | -- name = "Bennys Tuning", 21 | -- type = 566, 22 | -- scale = 0.8, 23 | -- color = 5, 24 | -- }, 25 | -- }, 26 | } 27 | 28 | return Config 29 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | --#-- 2 | --Fx info-- 3 | --#-- 4 | fx_version "cerulean" 5 | use_fxv2_oal "yes" 6 | lua54 "yes" 7 | game "gta5" 8 | version "1.0.2" 9 | 10 | --#-- 11 | --Manifest-- 12 | --#-- 13 | client_scripts { 14 | "client/functions/utils.lua", 15 | "client/functions/payment.lua", 16 | "client/functions/menu.lua", 17 | "client/bridge/esx.lua", 18 | "client/bridge/ox.lua", 19 | "client/bridge/qb.lua", 20 | "client/bridge/custom.lua", 21 | "client/client.lua" 22 | } 23 | 24 | server_scripts { 25 | "@oxmysql/lib/MySQL.lua", 26 | "server/server.lua", 27 | "server/bridge/esx.lua", 28 | "server/bridge/ox.lua", 29 | "server/bridge/qb.lua", 30 | "server/bridge/custom.lua", 31 | } 32 | 33 | shared_scripts { 34 | "@ox_lib/init.lua", 35 | } 36 | 37 | files { 38 | "config.lua", 39 | "client/vehicle/vehicles.lua", 40 | "client/vehicle/modList.lua", 41 | "client/vehicle/colorList.lua", 42 | "locales/*.json" 43 | } 44 | -------------------------------------------------------------------------------- /locales/cs.json: -------------------------------------------------------------------------------- 1 | { 2 | "base_mod": "Základní", 3 | 4 | "turbo_enabled": "Přidat", 5 | "turbo_disabled": "Odebrat", 6 | 7 | "upgrade_category_title": "Tuning výkonu", 8 | "description_upgrades": "Uprav výkon vozidla!", 9 | 10 | "engine_title": "Motor", 11 | "brakes_title": "Brzdy", 12 | "transmission_title": "Převodovka", 13 | "suspension_title": "Výška vozidla", 14 | "armor_title": "Plátování", 15 | "turbo_title": "Turbo", 16 | 17 | "tuning_menu_title": "Menu mechanika", 18 | 19 | "disable_xenon": "Odebrat", 20 | "xenon_title": "Světla", 21 | 22 | "disable_neon": "Odebrat", 23 | "color_neon": "Barva", 24 | 25 | "color_title": "Barvy", 26 | "primary_color_title": "Primární barva", 27 | "secondary_color_title": "Sekundární barva", 28 | "pearlescent_color_title": "Odlesk barvy", 29 | "select_color": "Vybrat barvu", 30 | "color_input": "Vložit barvu", 31 | "color_type": "Typ barvy", 32 | "color_type_normal": "Normální", 33 | "color_type_metalic": "Metalická", 34 | "color_type_pearl": "Perleťová", 35 | "color_type_matte": "Matná", 36 | "color_type_metal": "Metalová", 37 | "color_type_chrome": "Chromová", 38 | 39 | "cosmetics_title": "Kosmetika", 40 | "description_cosmetics": "Uprav vzhled vozidla!", 41 | "neon_title": "Neony", 42 | "wheels_title": "Kola", 43 | "horn_title": "Klaksony", 44 | "plates_title": "SPZ", 45 | "plate_holder_title": "Zadní - SPZ", 46 | "plate_vanity_title": "Přední - SPZ", 47 | "interior_title": "Interiér", 48 | "trim_title": "Dekorace", 49 | "dashboard_title": "Palubová deska", 50 | "speedometer_title": "Budíky", 51 | "door_speakers_title": "Dveřní repráky", 52 | "seats_title": "Sedadla", 53 | "steering_wheel_title": "Volant", 54 | "gears_title": "Řadící páka", 55 | "quarter_deck_title": "Nárazník", 56 | "speakers_title": "Reproduktory", 57 | "trunk_title": "Kufr", 58 | "hydrolic_title": "Hydraulika", 59 | "engine_block_title": "Motorový blok", 60 | "air_filter_title": "Vzduchový filtr", 61 | "struts_title": "Tlumiče", 62 | "arch_cover": "Kryt oblouku", 63 | "aerials_title": "Antény", 64 | "wings_title": "Křídla", 65 | "fuel_tank_title": "Palivová nádrž", 66 | "windows_title": "Okna", 67 | "livery_title": "Polepy", 68 | 69 | "body_parts_title": "Části vozidla", 70 | "spoiler_title": "Spoilery", 71 | "front_bumper_title": "Přední stínítko", 72 | "rear_bumper_title": "Zadní stínítko", 73 | "side_skirt_title": "Boční práh", 74 | "exhaust_title": "Výfuk", 75 | "cage_title": "Klec", 76 | "grille_title": "Maska", 77 | "hood_title": "Kapota", 78 | "left_fender_title": "Levý nárazník", 79 | "right_fender_title": "Pravý nárazník", 80 | "roof_title": "Střecha", 81 | 82 | "window_tint_title": "Zatmavení skel", 83 | "tint_pure_black": "Úroveň 4 (Pure Black)", 84 | "tint_darksmoke": "Úroveň 3 (Darksmoke)", 85 | "tint_lightsmoke": "Úroveň 2 (Lightsmoke)", 86 | "tint_limo": "Úroveň 1 (limo)", 87 | "tint_green": "Zelené", 88 | 89 | "plate_color_title": "Barva SPZ", 90 | "plate_blue_on_white1": "Modrá na bílé 1", 91 | "plate_blue_on_white2": "Modrá na bílé 2", 92 | "plate_blue_on_white3": "Modrá na bílé 3", 93 | "plate_yellow_black": "Žlutá na černé", 94 | "plate_yellow_blue": "Žlutá na modré", 95 | 96 | "wheel_menu_title": "Výběr kol", 97 | "wheel_color_title": "Barva kol", 98 | "wheel_smoke_title": "Kouř kol", 99 | 100 | "wheel_type_title": "Typ kol", 101 | "wheel_type_sport": "Sportovní", 102 | "wheel_type_muscle": "Muscle", 103 | "wheel_type_lowrider": "Lowrider", 104 | "wheel_type_suv": "SUV", 105 | "wheel_type_offroad": "Off-Road", 106 | "wheel_type_tuner": "Tuner", 107 | "wheel_type_bike": "Bike", 108 | "wheel_type_highend": "High-End", 109 | 110 | "no_money": "dost peněz" 111 | } 112 | -------------------------------------------------------------------------------- /locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "base_mod": "Default", 3 | 4 | "turbo_enabled": "Enabled", 5 | "turbo_disabled": "Disabled", 6 | 7 | "upgrade_category_title": "Upgrades", 8 | "description_upgrades": "Max this shit out", 9 | 10 | "engine_title": "Engine", 11 | "brakes_title": "Brakes", 12 | "transmission_title": "Transmission", 13 | "suspension_title": "Suspension", 14 | "armor_title": "Armor", 15 | "turbo_title": "Turbo", 16 | 17 | "tuning_menu_title": "Tuning Menu", 18 | 19 | "disable_xenon": "Disable", 20 | "xenon_title": "Xenon Lights", 21 | 22 | "disable_neon": "Disable", 23 | "color_neon": "Color", 24 | 25 | "color_title": "Colors", 26 | "primary_color_title": "Primary Color", 27 | "secondary_color_title": "Secondary Color", 28 | "pearlescent_color_title": "Pearlescent Colors", 29 | "select_color": "Select Color", 30 | "color_input": "Color Input", 31 | "color_type": "Color Type", 32 | "color_type_normal": "Normal", 33 | "color_type_metalic": "Metalic", 34 | "color_type_pearl": "Pearl", 35 | "color_type_matte": "Matte", 36 | "color_type_metal": "Metal", 37 | "color_type_chrome": "Chrome", 38 | 39 | "cosmetics_title": "Cosmetics", 40 | "description_cosmetics": "Modify the estethics of the vehicle", 41 | "neon_title": "Neons", 42 | "wheels_title": "Wheels", 43 | "horn_title": "Horns", 44 | "plates_title": "Plates", 45 | "plate_holder_title": "Back - Plate", 46 | "plate_vanity_title": "Front - Plate", 47 | "interior_title": "Interiors", 48 | "trim_title": "Trim", 49 | "dashboard_title": "Dashboard", 50 | "speedometer_title": "Speedometer", 51 | "door_speakers_title": "Door Speakers", 52 | "seats_title": "Seats", 53 | "steering_wheel_title": "Steering Wheel", 54 | "gears_title": "Gears", 55 | "quarter_deck_title": "Quarter Deck", 56 | "speakers_title": "Speakers", 57 | "trunk_title": "Trunk", 58 | "hydrolic_title": "Hydrolic", 59 | "engine_block_title": "Engine Block", 60 | "air_filter_title": "Air Filter", 61 | "struts_title": "Struts", 62 | "arch_cover": "Arch Cover", 63 | "aerials_title": "Aerials", 64 | "wings_title": "Wings", 65 | "fuel_tank_title": "Fuel Tank", 66 | "windows_title": "Windows", 67 | "livery_title": "Livery", 68 | 69 | "body_parts_title": "Body Parts", 70 | "spoiler_title": "Spoilers", 71 | "front_bumper_title": "From Bumpers", 72 | "rear_bumper_title": "Rear Bumpers", 73 | "side_skirt_title": "Side Skirt", 74 | "exhaust_title": "Exhaust", 75 | "cage_title": "Cage", 76 | "grille_title": "Grille", 77 | "hood_title": "Hood", 78 | "left_fender_title": "Left Fender", 79 | "right_fender_title": "Right Fender", 80 | "roof_title": "Roof", 81 | 82 | "window_tint_title": "Window Tint", 83 | "tint_pure_black": "Pure Black", 84 | "tint_darksmoke": "Darksmoke", 85 | "tint_lightsmoke": "Lightsmoke", 86 | "tint_limo": "Limo", 87 | "tint_green": "Green", 88 | 89 | "plate_color_title": "Plate Color", 90 | "plate_blue_on_white1": "Blue On White 1", 91 | "plate_blue_on_white2": "Blue On White 2", 92 | "plate_blue_on_white3": "Blue On White 3", 93 | "plate_yellow_black": "Yellow On Black", 94 | "plate_yellow_blue": "Yellow On Blue", 95 | 96 | "wheel_menu_title": "Wheels Menu", 97 | "wheel_color_title": "Wheels Color", 98 | "wheel_smoke_title": "Wheels Smoke", 99 | 100 | "wheel_type_title": "Wheels Type", 101 | "wheel_type_sport": "Sports", 102 | "wheel_type_muscle": "Muscle", 103 | "wheel_type_lowrider": "Lowrider", 104 | "wheel_type_suv": "Suv", 105 | "wheel_type_offroad": "Offroad", 106 | "wheel_type_tuner": "Tuner", 107 | "wheel_type_bike": "Bike", 108 | "wheel_type_highend": "Highend", 109 | 110 | "no_money": "You dont have enough money" 111 | } 112 | -------------------------------------------------------------------------------- /locales/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "base_mod": "Default", 3 | 4 | "turbo_enabled": "Abilitato", 5 | "turbo_disabled": "Disabilita", 6 | 7 | "upgrade_category_title": "Aggiornamenti", 8 | "description_upgrades": "Max this shit out", 9 | 10 | "engine_title": "Motore", 11 | "brakes_title": "Freni", 12 | "transmission_title": "Trasmissione", 13 | "suspension_title": "Sospensione", 14 | "armor_title": "Armatura", 15 | "turbo_title": "Turbo", 16 | 17 | "tuning_menu_title": "Tuning Menu", 18 | 19 | "disable_xenon": "Disable", 20 | "xenon_title": "Luci Xenon", 21 | 22 | "disable_neon": "Disabilita", 23 | "color_neon": "Colore", 24 | 25 | "color_title": "Colori", 26 | "primary_color_title": "Colore Primario", 27 | "secondary_color_title": "Colore Secondario", 28 | "pearlescent_color_title": "Perlescenze", 29 | "select_color": "Seleziona Colore", 30 | "color_input": "Color Input", 31 | "color_type": "Tipo Colore", 32 | "color_type_normal": "Normale", 33 | "color_type_metalic": "Metallico", 34 | "color_type_pearl": "Perlescente", 35 | "color_type_matte": "Opaco", 36 | "color_type_metal": "Metallico", 37 | "color_type_chrome": "Cromatico", 38 | 39 | "cosmetics_title": "Cosmetici", 40 | "description_cosmetics": "Modifica l' estetica del veicolo", 41 | "neon_title": "Neons", 42 | "wheels_title": "Ruote", 43 | "horn_title": "Clakcson", 44 | "plates_title": "Targhe", 45 | "plate_holder_title": "Targa - Posteriore", 46 | "plate_vanity_title": "Targa - Anteriore", 47 | "interior_title": "Interni", 48 | "trim_title": "Trim", 49 | "dashboard_title": "Dashboard", 50 | "speedometer_title": "Cruscotto", 51 | "door_speakers_title": "Autoparlanti", 52 | "seats_title": "Sedili", 53 | "steering_wheel_title": "Steering Wheel", 54 | "gears_title": "Marce", 55 | "quarter_deck_title": "Quarter Deck", 56 | "speakers_title": "Autoparlanti", 57 | "trunk_title": "Trunk", 58 | "hydrolic_title": "Idraulica", 59 | "engine_block_title": "Blocco Motore", 60 | "air_filter_title": "Filtro Aria", 61 | "struts_title": "Struts", 62 | "arch_cover": "Arch Cover", 63 | "aerials_title": "Antenne", 64 | "wings_title": "Ali", 65 | "fuel_tank_title": "Tanica Benzina", 66 | "windows_title": "Finestrini", 67 | "livery_title": "Livrea", 68 | 69 | "body_parts_title": "Body Parts", 70 | "spoiler_title": "Spoilers", 71 | "front_bumper_title": "Paraurti Anteriore", 72 | "rear_bumper_title": "Paraurti Posteriore", 73 | "side_skirt_title": "Minigonne", 74 | "exhaust_title": "Marmitta", 75 | "cage_title": "Dettagli", 76 | "grille_title": "Griglia", 77 | "hood_title": "Cofano", 78 | "left_fender_title": "Parafango Sinistro", 79 | "right_fender_title": "Parafango Destro", 80 | "roof_title": "Tettuccio", 81 | 82 | "window_tint_title": "Tinta Finestrini", 83 | "tint_pure_black": "Nero Puro", 84 | "tint_darksmoke": "Sfumato Scuro", 85 | "tint_lightsmoke": "Sfumato Chiaro", 86 | "tint_limo": "Limousine", 87 | "tint_green": "Verde", 88 | 89 | "plate_color_title": "Colore Targhe", 90 | "plate_blue_on_white1": "Blu su Bianco 1", 91 | "plate_blue_on_white2": "Blu su Bianco 2", 92 | "plate_blue_on_white3": "Blu su Bianco 3", 93 | "plate_yellow_black": "Giallo su Nero", 94 | "plate_yellow_blue": "Giallo su Blu", 95 | 96 | "wheel_menu_title": "Menu Cerchioni", 97 | "wheel_color_title": "Colore Cerchioni", 98 | "wheel_smoke_title": "Sfumatura Cerchioni", 99 | 100 | "wheel_type_title": "Tipo Cerchioni", 101 | "wheel_type_sport": "Sports", 102 | "wheel_type_muscle": "Muscle", 103 | "wheel_type_lowrider": "Lowrider", 104 | "wheel_type_suv": "Suv", 105 | "wheel_type_offroad": "Fuori Strada", 106 | "wheel_type_tuner": "Tuner", 107 | "wheel_type_bike": "Moto", 108 | "wheel_type_highend": "Highend", 109 | 110 | "no_money": "Non hai abbastanza soldi" 111 | } 112 | -------------------------------------------------------------------------------- /server/bridge/custom.lua: -------------------------------------------------------------------------------- 1 | -- local ox = GetResourceState('ox_core'):find("start") 2 | -- if not ox then return end 3 | 4 | -- --- @param amount number 5 | -- lib.callback.register('ars_tuning:hasMoney', function(source, amount) 6 | -- local money = exports.ox_inventory:Search(source, "count", "money") 7 | 8 | -- return money >= amount 9 | -- end) 10 | 11 | -- --- @param amount number 12 | -- RegisterNetEvent("ars_tuning:payMods", function(amount, properties) 13 | -- exports.ox_inventory:RemoveItem(source, "money", amount) 14 | 15 | -- local properties = properties 16 | -- local isVehicleOwned = MySQL.prepare.await('SELECT plate,data FROM vehicles WHERE plate = ?', { properties.plate }) 17 | 18 | -- if isVehicleOwned then 19 | -- local data = json.decode(isVehicleOwned.data) 20 | -- data.properties = properties 21 | 22 | -- local newData = json.encode(data) 23 | 24 | -- MySQL.update('UPDATE vehicles SET data = ? WHERE plate = ?', { newData, properties.plate }) 25 | -- end 26 | -- end) 27 | -------------------------------------------------------------------------------- /server/bridge/esx.lua: -------------------------------------------------------------------------------- 1 | local esx = GetResourceState('es_extended'):find('start') 2 | if not esx then return end 3 | 4 | local ESX = exports.es_extended:getSharedObject() 5 | 6 | --- @param amount number 7 | lib.callback.register('ars_tuning:hasMoney', function(source, amount) 8 | local xPlayer = ESX.GetPlayerFromId(source) 9 | 10 | local money = xPlayer.getAccount("money").money 11 | 12 | return money >= amount 13 | end) 14 | 15 | --- @param amount number 16 | RegisterNetEvent("ars_tuning:payMods", function(amount, properties) 17 | local xPlayer = ESX.GetPlayerFromId(source) 18 | 19 | xPlayer.removeAccountMoney("money", amount) 20 | 21 | 22 | local properties = properties 23 | local isVehicleOwned = MySQL.prepare.await('SELECT plate FROM owned_vehicles WHERE plate = ?', { properties.plate }) 24 | 25 | if isVehicleOwned then 26 | MySQL.update('UPDATE owned_vehicles SET vehicle = ? WHERE plate = ?', 27 | { json.encode(properties), properties.plate }) 28 | end 29 | end) 30 | -------------------------------------------------------------------------------- /server/bridge/ox.lua: -------------------------------------------------------------------------------- 1 | local ox = GetResourceState('ox_core'):find("start") 2 | if not ox then return end 3 | 4 | --- @param amount number 5 | lib.callback.register('ars_tuning:hasMoney', function(source, amount) 6 | local money = exports.ox_inventory:Search(source, "count", "money") 7 | 8 | return money >= amount 9 | end) 10 | 11 | --- @param amount number 12 | RegisterNetEvent("ars_tuning:payMods", function(amount, properties) 13 | exports.ox_inventory:RemoveItem(source, "money", amount) 14 | 15 | local properties = properties 16 | local isVehicleOwned = MySQL.prepare.await('SELECT plate,data FROM vehicles WHERE plate = ?', { properties.plate }) 17 | 18 | if isVehicleOwned then 19 | local data = json.decode(isVehicleOwned.data) 20 | data.properties = properties 21 | 22 | local newData = json.encode(data) 23 | 24 | MySQL.update('UPDATE vehicles SET data = ? WHERE plate = ?', { newData, properties.plate }) 25 | end 26 | end) 27 | -------------------------------------------------------------------------------- /server/bridge/qb.lua: -------------------------------------------------------------------------------- 1 | local qb = GetResourceState('qb-core'):find("start") 2 | if not qb then return end 3 | 4 | local QBCore = exports['qb-core']:GetCoreObject() 5 | 6 | --- @param amount number 7 | lib.callback.register('ars_tuning:hasMoney', function(source, amount) 8 | local xPlayer = QBCore.Functions.GetPlayer(source) 9 | 10 | local money = xPlayer.Functions.GetMoney('cash') 11 | 12 | return money >= amount 13 | end) 14 | 15 | --- @param amount number 16 | RegisterNetEvent("ars_tuning:payMods", function(amount, properties) 17 | local xPlayer = QBCore.Functions.GetPlayer(source) 18 | 19 | xPlayer.Functions.RemoveMoney('cash', amount) 20 | 21 | local properties = properties 22 | local isVehicleOwned = MySQL.prepare.await('SELECT plate FROM player_vehicles WHERE plate = ?', { properties.plate }) 23 | 24 | if isVehicleOwned then 25 | MySQL.update('UPDATE player_vehicles SET mods = ? WHERE plate = ?', 26 | { json.encode(properties), properties.plate }) 27 | end 28 | end) 29 | -------------------------------------------------------------------------------- /server/server.lua: -------------------------------------------------------------------------------- 1 | lib.versionCheck('Arius-Development/ars_tuning') --------------------------------------------------------------------------------