local currentMechanicId = nil local isMenuOpen = false local isPromptShowing = false local currentVehicle = nil local originalVehicleProps = {} local vehiclePlate = "" local isPurchaseFinalized = false local isDoingBurnout = false local canTyresBeBurst = true local isFreecamActive = false local isHornLoopActive = false local appliedMods = { repair = {}, performance = {}, cosmetics = {}, stance = {}, respray = {}, wheels = {}, neonLights = {}, headlights = {}, tyreSmoke = {}, bulletproofTyres = {}, extras = {} } local function toggleVehicleFreeze(vehicle, shouldFreeze) if not vehicle then return end SetVehicleEngineOn(vehicle, not shouldFreeze, true, true) FreezeEntityPosition(vehicle, shouldFreeze) SetEntityCollision(vehicle, not shouldFreeze, not shouldFreeze) end local function stopBurnoutPreview() if not currentVehicle then return end ClearPedTasks(cache.ped) SetVehicleTyresCanBurst(currentVehicle, canTyresBeBurst) SetVehicleCurrentRpm(currentVehicle, 0) FreezeEntityPosition(currentVehicle, true) SetEntityCollision(currentVehicle, false, false) SetVehicleEngineOn(currentVehicle, false, true, true) isDoingBurnout = false end local function revertToOriginalMods() if not currentVehicle then return end if isPurchaseFinalized then return end setVehicleProperties(currentVehicle, originalVehicleProps, true) end local function getModSlotName(vehicle, modType) if type(modType) == "string" then return false end local label = GetLabelText(GetModSlotName(vehicle, modType)) if label ~= "NULL" then return label end local rawName = GetModSlotName(vehicle, modType) if rawName and rawName ~= "" then return rawName end return false end local function getModName(vehicle, modType, modSlotName, modIndex) if modType == "LIVERY" then local label = GetLabelText(GetLiveryName(vehicle, modIndex)) if label ~= "NULL" then return label end end if type(modType) == "string" then return "ERROR" end local label = GetLabelText(GetModTextLabel(vehicle, modType, modIndex)) if label ~= "NULL" then return label end local rawLabel = GetModTextLabel(vehicle, modType, modIndex) if rawLabel and rawLabel ~= "" then return rawLabel end return (modSlotName or "") .. " " .. (modIndex + 1) end local function isModInCameraGroup(modGroup, vehicle, modId) for _, mod in ipairs(modGroup) do if modId == mod then return true elseif type(mod) == "string" and type(modId) == "number" then local slotName = GetModSlotName(vehicle, modId) if slotName == mod then return true end end end return false end local function getAvailableMods(vehicle, originalProps, mechanicId) local mechanicConfig = Config.MechanicLocations[mechanicId] local allowedMods = mechanicConfig.mods if not allowedMods then return false end if Config.ModsPricesAsPercentageOfVehicleValue then local vehicleValue = Framework.Client.GetVehicleValue(GetEntityArchetypeName(vehicle)) for modCategory in pairs(allowedMods) do local categoryData = allowedMods[modCategory] categoryData.price = round(vehicleValue * (categoryData.percentVehVal or 0.01), 0) end end local vehicleModel = GetEntityModel(vehicle) SetVehicleModKit(vehicle, 0) local performanceMods = {} for _, modInfo in pairs(Config.Mods.Performance) do local modCount = GetNumVehicleMods(vehicle, modInfo.modType) if modCount > 0 or modInfo.toggle then local slotName = getModSlotName(vehicle, modInfo.modType) or modInfo.name local modsList = { { modIndex = -1, name = "Stock" } } if modInfo.overrideOptions and type(modInfo.overrideOptions) == "table" then for _, overrideOption in pairs(modInfo.overrideOptions) do modsList[#modsList + 1] = { modIndex = overrideOption.modIndex, name = overrideOption.name, price = overrideOption.price or round(allowedMods.performance.price * (1 + overrideOption.modIndex * (allowedMods.performance.priceMult or 0)), 0) } end else for i = 0, modCount - 1 do modsList[#modsList + 1] = { modIndex = i, name = getModName(vehicle, modInfo.modType, slotName, i), price = round(allowedMods.performance.price * (i > 0 and (1 + i * (allowedMods.performance.priceMult or 0)) or 1), 0) } end end performanceMods[#performanceMods + 1] = { modType = modInfo.modType, name = slotName, mods = modsList, toggle = modInfo.toggle, price = allowedMods.performance.price } end end local cosmeticMods = {} for _, modInfo in pairs(Config.Mods.Cosmetics) do local slotName = modInfo.name local ignorePriceMult = modInfo.ignorePriceMult local options = {} if modInfo.modType == "PLATE_INDEX" then if IsThisModelACar(vehicleModel) or IsThisModelAQuadbike(vehicleModel) or IsThisModelABike(vehicleModel) then for i = 1, #Config.Mods.PlateIndexes do if i < 6 or GetGameBuildNumber() >= 3095 then options[#options + 1] = Config.Mods.PlateIndexes[i] local price = ignorePriceMult and allowedMods.cosmetics.price or round(allowedMods.cosmetics.price * (i > 0 and (1 + i * (allowedMods.cosmetics.priceMult or 0)) or 1), 0) options[i].price = price end end end elseif modInfo.modType == "WINDOW_TINT" then if not IsThisModelABicycle(vehicleModel) then for i = 1, #Config.Mods.WindowTints do options[#options + 1] = Config.Mods.WindowTints[i] local price = ignorePriceMult and allowedMods.cosmetics.price or round(allowedMods.cosmetics.price * (i > 0 and (1 + i * (allowedMods.cosmetics.priceMult or 0)) or 1), 0) options[i].price = price end end else local modCount = 0 if modInfo.modType == "LIVERY" then modCount = GetVehicleLiveryCount(vehicle) elseif modInfo.modType == "LIVERY_ROOF" then modCount = GetVehicleRoofLiveryCount(vehicle) else modCount = GetNumVehicleMods(vehicle, modInfo.modType) end if modCount > 0 or modInfo.toggle then slotName = getModSlotName(vehicle, modInfo.modType) or slotName or modInfo.name if modInfo.modType == 14 then for i = 1, #Config.Mods.Horns do options[#options + 1] = Config.Mods.Horns[i] local price = ignorePriceMult and allowedMods.cosmetics.price or round(allowedMods.cosmetics.price * (i > 0 and (1 + i * (allowedMods.cosmetics.priceMult or 0)) or 1), 0) options[i].price = price end else options = { { modIndex = -1, name = "Stock" } } for i = 0, modCount - 1 do local name = Config.UseCustomNamesInTuningMenu and modInfo.name or getModName(vehicle, modInfo.modType, slotName, i) local price = ignorePriceMult and allowedMods.cosmetics.price or round(allowedMods.cosmetics.price * (i > 0 and (1 + i * (allowedMods.cosmetics.priceMult or 0)) or 1), 0) options[#options + 1] = { modIndex = i, name = name, price = price } end end end end if #options > 0 then local displayName = Config.UseCustomNamesInTuningMenu and modInfo.name or slotName cosmeticMods[#cosmeticMods + 1] = { modType = modInfo.modType, name = displayName, mods = options, toggle = modInfo.toggle, price = allowedMods.cosmetics.price } end end local wheelMods = {} if IsThisModelACar(vehicleModel) or IsThisModelAQuadbike(vehicleModel) or IsThisModelABike(vehicleModel) then for _, wheelType in ipairs(Config.Mods.WheelTypes) do local isCorrectVehicleType = (IsThisModelACar(vehicleModel) or IsThisModelAQuadbike(vehicleModel)) or (IsThisModelABike(vehicleModel) and wheelType.modIndex == 6) if isCorrectVehicleType then SetVehicleWheelType(vehicle, wheelType.modIndex) local modCount = GetNumVehicleMods(vehicle, 23) if modCount > 0 then local options = { { modIndex = -1, name = "Stock" } } for i = 0, modCount - 1 do options[#options + 1] = { modIndex = i, name = getModName(vehicle, 23, wheelType.name, i), price = round(allowedMods.wheels.price * (i > 0 and (1 + i * (allowedMods.wheels.priceMult or 0)) or 1), 0) } end wheelMods[#wheelMods + 1] = { modType = wheelType.modIndex, name = wheelType.name, mods = options } end end end end SetVehicleWheelType(vehicle, originalProps.wheels) if originalProps.modFrontWheels then SetVehicleMod(vehicle, 23, originalProps.modFrontWheels, originalProps.modCustomTiresF) end if originalProps.modBackWheels then SetVehicleMod(vehicle, 24, originalProps.modBackWheels, originalProps.modCustomTiresR) end local modCategories = {} if allowedMods.repair and allowedMods.repair.enabled then modCategories.repair = allowedMods.repair end if allowedMods.performance and allowedMods.performance.enabled and #performanceMods > 0 then modCategories.performance = performanceMods end if allowedMods.cosmetics and allowedMods.cosmetics.enabled and #cosmeticMods > 0 then modCategories.cosmetics = cosmeticMods end if IsThisModelACar(vehicleModel) and allowedMods.stance and allowedMods.stance.enabled then modCategories.stance = allowedMods.stance end if allowedMods.respray and allowedMods.respray.enabled and #Config.Mods.Colours > 0 then modCategories.respray = { price = allowedMods.respray.price, colours = Config.Mods.Colours } end if allowedMods.wheels and allowedMods.wheels.enabled and #wheelMods > 0 then modCategories.wheels = wheelMods end if allowedMods.neonLights then if (IsThisModelACar(vehicleModel) or IsThisModelAQuadbike(vehicleModel)) and allowedMods.neonLights.enabled then modCategories.neonLights = allowedMods.neonLights else modCategories.neonLights = { enabled = false, price = 0 } end end if allowedMods.headlights then if not IsThisModelABicycle(vehicleModel) and allowedMods.headlights.enabled then modCategories.headlights = allowedMods.headlights else modCategories.headlights = { enabled = false, price = 0 } end end if (IsThisModelACar(vehicleModel) or IsThisModelABike(vehicleModel) or IsThisModelAQuadbike(vehicleModel)) and allowedMods.tyreSmoke and allowedMods.tyreSmoke.enabled then modCategories.tyreSmoke = allowedMods.tyreSmoke end if (IsThisModelACar(vehicleModel) or IsThisModelABike(vehicleModel) or IsThisModelAQuadbike(vehicleModel)) and allowedMods.bulletproofTyres and allowedMods.bulletproofTyres.enabled then modCategories.bulletproofTyres = allowedMods.bulletproofTyres end if allowedMods.extras and allowedMods.extras.enabled and next(originalProps.extras) ~= nil then modCategories.extras = true end return modCategories end function closeModsMenu() if currentVehicle then toggleVehicleFreeze(currentVehicle, false) revertToOriginalMods() Entity(currentVehicle).state:set("unpaidModifications", false, true) end SetNuiFocusKeepInput(false) Framework.Client.ToggleHud(true) LocalPlayer.state:set("isBusy", false, true) appliedMods = { repair = {}, performance = {}, cosmetics = {}, stance = {}, respray = {}, wheels = {}, neonLights = {}, headlights = {}, tyreSmoke = {}, bulletproofTyres = {}, extras = {} } isMenuOpen = false currentVehicle = nil originalVehicleProps = nil isPurchaseFinalized = false end function openModsMenu(mechId, mechLabel) local mechanicConfig = Config.MechanicLocations[mechId] if not mechanicConfig then return false end currentMechanicId = mechId if not cache.vehicle then return false end currentVehicle = cache.vehicle if GetPedInVehicleSeat(currentVehicle, -1) ~= cache.ped then Framework.Client.Notify(Locale.notInDriversSeat, "error") currentVehicle = nil return false end local health = { GetVehicleBodyHealth(currentVehicle), GetVehicleEngineHealth(currentVehicle) } local props = getVehicleProperties(currentVehicle, true) if not props then error("Could not get the vehicle's props") end originalVehicleProps = props local plate = Framework.Client.GetPlate(currentVehicle) if not plate then error("Could not get the vehicle's plate") end vehiclePlate = plate canTyresBeBurst = not props.bulletProofTyres props.windowTint = math.max(props.windowTint, 0) local mods = getAvailableMods(currentVehicle, props, mechId) if not mods then return false end for i = 0, 5 do if GetPedInVehicleSeat(currentVehicle, i) ~= 0 then Framework.Client.Notify(Locale.passengersMustLeaveVehicleFirst, "error") return false end end toggleVehicleFreeze(currentVehicle, true) SetVehicleModKit(currentVehicle, 0) setupVehicleCamera(currentVehicle) if Config.ChangePlateDuringPreview then lib.callback.await("jg-mechanic:server:open-mods-menu", false, VehToNet(currentVehicle)) end local isMechanicEmployee = lib.callback.await("jg-mechanic:server:is-mechanic-employee", false, mechId) local mechanicBalance = isMechanicEmployee and lib.callback.await("jg-mechanic:server:get-mechanic-balance", false, mechId) or false local mechanicsOnDuty = lib.callback.await("jg-mechanic:server:count-currently-on-duty", false, mechId) local mechanicType = mechanicConfig.type ~= "self-service" and not (Config.MechanicEmployeesCanSelfServiceMods and isMechanicEmployee) and "owned" or "self-service" LocalPlayer.state:set("isBusy", true, true) Framework.Client.ToggleHud(false) SetNuiFocus(true, true) SendNUIMessage({ type = "show-vehicle-tuning", logo = mechanicConfig.logo, mechanicId = mechId, name = mechLabel or (mechLabel == "" and mechId or mechLabel), mechanicType = mechanicType, mechanicsOnDuty = mechanicsOnDuty, isMechanicEmployee = isMechanicEmployee, mechBalance = isMechanicEmployee and mechanicType == "self-service" and mechanicBalance or false, bankBalance = Framework.Client.GetBalance("bank"), cashBalance = Framework.Client.GetBalance("cash"), changeCamBtn = parseControlBinding(0), vehicleDamaged = health, props = props, mods = mods, config = Config, locale = Locale }) return true end RegisterNetEvent("jg-mechanic:client:open-customisation-menu", openModsMenu) onEnterModsZone = function(mechId, mechLabel) if not cache.vehicle then return false end CreateThread(function() currentMechanicId = mechId while currentMechanicId do Wait(0) if not isMenuOpen and not isPromptShowing then Framework.Client.ShowTextUI(Config.CustomiseVehiclePrompt) isPromptShowing = true end if IsControlJustPressed(0, Config.CustomiseVehicleKey) and not isMenuOpen then if openModsMenu(currentMechanicId, mechLabel) then isMenuOpen = true isPromptShowing = false Framework.Client.HideTextUI() end end end end) end onExitModsZone = function() currentMechanicId = nil closeModsMenu() SetTimeout(1, function() Framework.Client.HideTextUI() isPromptShowing = false end) end RegisterNUICallback("purchase-mods", function(data, cb) if not (currentMechanicId and currentVehicle and originalVehicleProps and currentVehicle) then return cb({ error = true }) end local cart = data.cart local paymentMethod = data.paymentMethod if not cart or type(cart) ~= "table" then return cb({ error = true }) end local mechanicConfig = Config.MechanicLocations[currentMechanicId] if not mechanicConfig then return cb({ error = false }) end local currentProps = getVehicleProperties(currentVehicle, true) currentProps.plate = vehiclePlate if not currentProps then return cb({ error = false }) end local vehicleValue = Framework.Client.GetVehicleValue(GetEntityArchetypeName(currentVehicle)) local amountPaid = lib.callback.await("jg-mechanic:server:purchase-mods", false, currentMechanicId, vehicleValue, cart, paymentMethod) if amountPaid == false then return cb({ error = true }) end amountPaid = tonumber(amountPaid) or 0 local isMechanicEmployee = lib.callback.await("jg-mechanic:server:is-mechanic-employee", false, currentMechanicId) if mechanicConfig.type == "self-service" or (Config.MechanicEmployeesCanSelfServiceMods and isMechanicEmployee) then toggleVehicleFreeze(currentVehicle, false) local combinedMods = {} for _, category in pairs(appliedMods) do combinedMods = tableConcat(combinedMods, category) end setStatebagsFromProps(currentVehicle, combinedMods, vehiclePlate) lib.callback.await("jg-mechanic:server:save-veh-statebag-data-to-db", false, vehiclePlate) isPurchaseFinalized = true lib.callback.await("jg-mechanic:server:self-service-mods-applied", false, currentMechanicId, VehToNet(currentVehicle), vehiclePlate, cart, amountPaid, paymentMethod) if Config.UpdatePropsOnChange then lib.callback.await("jg-mechanic:server:save-vehicle-props", false, vehiclePlate, currentProps) end if originalVehicleProps and currentProps then originalVehicleProps.wheels = currentProps.wheels originalVehicleProps.modFrontWheels = currentProps.modFrontWheels originalVehicleProps.modBackWheels = currentProps.modBackWheels end else local orderPlaced = lib.callback.await("jg-mechanic:server:place-order", false, currentMechanicId, vehiclePlate, cart, amountPaid, appliedMods, paymentMethod) if not orderPlaced then return cb({ error = true }) end end cb(true) end) RegisterNUICallback("exit-mods", function(data, cb) closeModsMenu() cb(true) end) RegisterNUICallback("switch-camera", function(data, cb) if not currentVehicle then return cb(false) end local modId = data and data.modId CreateThread(function() SetVehicleDoorsShut(currentVehicle, true) if IsVehicleDoorDamaged(currentVehicle, 4) then SetVehicleFixed(currentVehicle) end stopBurnoutPreview() if isModInCameraGroup({ "TOP_HL_CV", "TOP_HLT", "TOP_SUNST", "HEADLIGHTS", "TOP_SPLIT" }, currentVehicle, modId) then transitionCamera("frontCamera") elseif isModInCameraGroup({ "TOP_TRUNK", "TOP_BOOT", "TOP_TGATE", "TOP_RPNL", "TOP_WINP", "TOP_WBAR", "TOP_COVER", "TOP_LOUV" }, currentVehicle, modId) then transitionCamera("backCamera") elseif isModInCameraGroup({ "TOP_CAGE" }, currentVehicle, modId) then transitionCamera("interior") elseif isModInCameraGroup({ "TOP_ROOFSC", "TOP_ROOFFIN" }, currentVehicle, modId) then transitionCamera("roof") elseif isModInCameraGroup({ "TOP_VALHD", "TOP_ENGHD" }, currentVehicle, modId) then transitionCamera("backCamera") SetVehicleDoorOpen(currentVehicle, 4, false, true) elseif isModInCameraGroup({ "TOP_SIDE_PAN", "TOP_MIR" }, currentVehicle, modId) then transitionCamera("sideCamera") elseif isModInCameraGroup({ "TOP_CATCH" }, currentVehicle, modId) then transitionCamera("engineBay") elseif isModInCameraGroup({ "TOP_ENGINE", "TOP_BRACE", "TOP_ENGD" }, currentVehicle, modId) then transitionCamera("engineBay") if GetEntityArchetypeName(currentVehicle) == "z190" then SetVehicleDoorBroken(currentVehicle, 4, true) end SetVehicleDoorOpen(currentVehicle, 4, false, true) elseif isModInCameraGroup({ 1, 6, 26, 42, 43 }, currentVehicle, modId) then transitionCamera("frontCamera") elseif isModInCameraGroup({ 37 }, currentVehicle, modId) then transitionCamera("backCamera") SetVehicleDoorOpen(currentVehicle, 5, false, true) elseif isModInCameraGroup({ 5, 27, 32, "COLOR_INTERIOR" }, currentVehicle, modId) then transitionCamera("interior") elseif isModInCameraGroup({ 4 }, currentVehicle, modId) then transitionCamera("exhaust") elseif isModInCameraGroup({ 0, 2, 4, 25, "PLATE_INDEX" }, currentVehicle, modId) then transitionCamera("backCamera") elseif isModInCameraGroup({ 3, 8, 23, 24, "WHEELS" }, currentVehicle, modId) then transitionCamera("sideCamera") elseif isModInCameraGroup({ 7 }, currentVehicle, modId) then transitionCamera("engineBay") elseif isModInCameraGroup({ 39, 40, 41 }, currentVehicle, modId) then transitionCamera("engineBay") if GetEntityArchetypeName(currentVehicle) == "banshee2" then SetVehicleDoorBroken(currentVehicle, 4, true) end SetVehicleDoorOpen(currentVehicle, 4, false, true) elseif isModInCameraGroup({ 31 }, currentVehicle, modId) then transitionCamera("doorSpeaker") elseif isModInCameraGroup({ 28, 29, 30, 33, 34, "COLOR_DASHBOARD" }, currentVehicle, modId) then transitionCamera("pov") else transitionCamera("default") end cb(true) end) end) RegisterNUICallback("toggle-freecam", function(data, cb) if data.enable then isFreecamActive = true toggleCamTemporarily(false) else toggleCamTemporarily(true) isFreecamActive = false end cb(true) end) RegisterNUICallback("move-freecam", function(data, cb) if not isFreecamActive then return cb(false) end SetNuiFocus(true, false) SetNuiFocusKeepInput(true) CreateThread(function() while isFreecamActive do DisableAllControlActions(0) EnableControlAction(0, 0, false) EnableControlAction(0, 1, true) EnableControlAction(0, 2, true) EnableControlAction(0, 59, true) Wait(0) end end) cb(true) end) RegisterNUICallback("stop-moving-freecam", function(data, cb) SetNuiFocus(true, true) SetNuiFocusKeepInput(false) cb(true) end) RegisterNUICallback("repair-vehicle", function(data, cb) if not (currentVehicle and currentVehicle) then return cb(false) end local vehicleValue = Framework.Client.GetVehicleValue(GetEntityArchetypeName(currentVehicle)) local success = lib.callback.await("jg-mechanic:server:self-service-repair-vehicle", false, currentMechanicId, vehicleValue, data and data.paymentMethod) if success then Framework.Client.RepairVehicle(currentVehicle) if originalVehicleProps then originalVehicleProps.dirtLevel = 0.0 originalVehicleProps.engineHealth = 1000.0 originalVehicleProps.bodyHealth = 1000.0 originalVehicleProps.tankHealth = 1000.0 originalVehicleProps.windowStatus = nil originalVehicleProps.doorStatus = nil originalVehicleProps.tireHealth = nil originalVehicleProps.tireBurstState = nil originalVehicleProps.tireBurstCompletely = nil originalVehicleProps.windowsBroken = nil originalVehicleProps.doorsBroken = nil originalVehicleProps.tyreBurst = nil end end cb(true) end) RegisterNUICallback("preview-performance-mod", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) local propKey = data.propKey local modType = data.modType local modIndex = data.modIndex local toggleMod = data.toggleMod SetVehicleModKit(currentVehicle, 0) if toggleMod then ToggleVehicleMod(currentVehicle, modType, modIndex) appliedMods.performance[propKey] = modIndex elseif type(modType) == "number" then SetVehicleMod(currentVehicle, modType, modIndex, false) appliedMods.performance[propKey] = modIndex end cb(true) end) RegisterNUICallback("preview-cosmetic-mod", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) local propKey = data.propKey local modType = data.modType local modIndex = data.modIndex local toggleMod = data.toggleMod SetVehicleModKit(currentVehicle, 0) if modType == "LIVERY" then SetVehicleLivery(currentVehicle, modIndex) elseif modType == "LIVERY_ROOF" then SetVehicleRoofLivery(currentVehicle, modIndex) elseif modType == "PLATE_INDEX" then SetVehicleNumberPlateTextIndex(currentVehicle, modIndex) elseif modType == "WINDOW_TINT" then SetVehicleWindowTint(currentVehicle, modIndex) elseif modType == 14 then SetVehicleMod(currentVehicle, 14, modIndex, false) Citizen.CreateThreadNow(function() if isHornLoopActive then isHornLoopActive = false Wait(10) end isHornLoopActive = true local duration = Config.Mods.Horns[modIndex + 2].musical and 750 or 100 while duration > 1 do if not isHornLoopActive then break end SetControlNormal(0, 86, 1.0) Wait(1) duration = duration - 1 end end) elseif toggleMod then ToggleVehicleMod(currentVehicle, modType, modIndex) elseif type(modType) == "number" then SetVehicleMod(currentVehicle, modType, modIndex, false) end appliedMods.cosmetics[propKey] = modIndex cb(true) end) RegisterNUICallback("preview-wheels", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) SetVehicleModKit(currentVehicle, 0) SetVehicleWheelType(currentVehicle, data.modType) appliedMods.wheels.wheels = data.modType SetVehicleMod(currentVehicle, 23, data.modIndex, false) appliedMods.wheels.modFrontWheels = data.modIndex if IsThisModelABike(GetEntityModel(currentVehicle)) then SetVehicleMod(currentVehicle, 24, data.modIndex, false) appliedMods.wheels.modBackWheels = data.modIndex end appliedMods.wheels.wheelWidth = GetVehicleWheelWidth(currentVehicle) appliedMods.wheels.wheelSize = GetVehicleWheelSize(currentVehicle) cb(true) end) RegisterNUICallback("preview-pri-sec-colours", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) SetVehicleModKit(currentVehicle, 0) Entity(currentVehicle).state:set("primarySecondarySync", data.primarySecondarySync) appliedMods.respray.primarySecondarySync = data.primarySecondarySync if data.paintTypeKey == "paintType1" then if data.enableRgb then SetVehicleModColor_1(currentVehicle, data.paint, 0, 0) SetVehicleCustomPrimaryColour(currentVehicle, data.rgbColour[1], data.rgbColour[2], data.rgbColour[3]) appliedMods.respray.color1 = data.rgbColour else local _, sec = GetVehicleColours(currentVehicle) SetVehicleColours(currentVehicle, data.colourId, sec) ClearVehicleCustomPrimaryColour(currentVehicle) appliedMods.respray.color1 = data.colourId end appliedMods.respray.paintType1 = data.paint end if data.paintTypeKey == "paintType2" or data.primarySecondarySync then if data.enableRgb then SetVehicleModColor_2(currentVehicle, data.paint, 0) SetVehicleCustomSecondaryColour(currentVehicle, data.rgbColour[1], data.rgbColour[2], data.rgbColour[3]) appliedMods.respray.color2 = data.rgbColour else local pri, _ = GetVehicleColours(currentVehicle) SetVehicleColours(currentVehicle, pri, data.colourId) ClearVehicleCustomSecondaryColour(currentVehicle) appliedMods.respray.color2 = data.colourId end appliedMods.respray.paintType2 = data.paint end cb(true) end) RegisterNUICallback("preview-other-colours", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) SetVehicleModKit(currentVehicle, 0) if data.colourIdKey == "dashboardColor" then SetVehicleDashboardColor(currentVehicle, data.colourId) elseif data.colourIdKey == "interiorColor" then SetVehicleInteriorColor(currentVehicle, data.colourId) else local pearl, wheel = GetVehicleExtraColours(currentVehicle) if data.colourIdKey == "pearlescentColor" then SetVehicleExtraColours(currentVehicle, data.colourId, wheel) local disablePearl = data.disablePearl or false Entity(currentVehicle).state:set("disablePearl", disablePearl) appliedMods.respray.disablePearl = disablePearl end if data.colourIdKey == "wheelColor" then SetVehicleExtraColours(currentVehicle, pearl, data.colourId) end end appliedMods.respray[data.colourIdKey] = data.colourId cb(true) end) RegisterNUICallback("preview-xenons", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) SetVehicleModKit(currentVehicle, 0) ToggleVehicleMod(currentVehicle, 22, data.enableXenons) SetVehicleLights(currentVehicle, 2) SetVehicleXenonLightsColor(currentVehicle, data.xenonColor) appliedMods.headlights.modXenon = true appliedMods.headlights.xenonColor = data.xenonColor cb(true) end) RegisterNUICallback("preview-neons", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) SetVehicleModKit(currentVehicle, 0) for i = 0, 3 do SetVehicleNeonLightEnabled(currentVehicle, i, data.enableNeons[i + 1]) end SetVehicleNeonLightsColour(currentVehicle, data.neonColor[1], data.neonColor[2], data.neonColor[3]) appliedMods.neonLights.neonEnabled = data.enableNeons appliedMods.neonLights.neonColor = data.neonColor cb(true) end) RegisterNUICallback("preview-tyre-smoke", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) if isDoingBurnout and not data.enableTyreSmoke then stopBurnoutPreview() end if not isDoingBurnout and data.enableTyreSmoke then CreateThread(function() isDoingBurnout = true if canTyresBeBurst then SetVehicleTyresCanBurst(currentVehicle, false) end SetVehicleEngineOn(currentVehicle, true, true, true) SetEntityCollision(currentVehicle, true, true) FreezeEntityPosition(currentVehicle, false) TaskVehicleTempAction(cache.ped, currentVehicle, 30, 999999) end) end SetVehicleModKit(currentVehicle, 0) ToggleVehicleMod(currentVehicle, 20, data.enableTyreSmoke) SetVehicleTyreSmokeColor(currentVehicle, data.tyreSmokeColor[1], data.tyreSmokeColor[2], data.tyreSmokeColor[3]) appliedMods.tyreSmoke.modSmokeEnabled = data.enableTyreSmoke appliedMods.tyreSmoke.tyreSmokeColor = data.tyreSmokeColor cb(true) end) RegisterNUICallback("preview-bulletproof-tyres", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) local canBurst = not data.enableBulletproofTyres SetVehicleTyresCanBurst(currentVehicle, canBurst) canTyresBeBurst = canBurst appliedMods.bulletproofTyres.bulletProofTyres = data.enableBulletproofTyres cb(true) end) RegisterNUICallback("preview-extras", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) for extraId, enabled in pairs(data.extras) do SetVehicleExtra(currentVehicle, tonumber(extraId), not enabled) end appliedMods.extras.extras = data.extras cb(true) end) RegisterNUICallback("preview-stance", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) previewVehicleStance(currentVehicle, data.enableStance, data.defaultStance, data.stance) PreviewingNewStance = true cb(true) end) RegisterNUICallback("save-previewed-stance", function(data, cb) if not currentVehicle then return cb(false) end Entity(currentVehicle).state:set("unpaidModifications", true, true) setStanceState(currentVehicle, data.enableStance, data.wheelsAdjIndv, data.defaultStance, data.stance) PreviewingNewStance = false appliedMods.stance.enableStance = data.enableStance appliedMods.stance.wheelsAdjIndv = data.wheelsAdjIndv appliedMods.stance.defaultStance = data.defaultStance appliedMods.stance.stance = data.stance cb(true) end) AddEventHandler("onResourceStop", function(resourceName) if GetCurrentResourceName() == resourceName then if currentVehicle then revertToOriginalMods() Entity(currentVehicle).state:set("unpaidModifications", false, true) toggleVehicleFreeze(currentVehicle, false) end end end)