local Vehicles, myCar = {}, {}
local lsMenuIsShowed, HintDisplayed, isInLSMarker = false, false, false
local gameBuild = GetGameBuildNumber()
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function()
ESX.TriggerServerCallback('esx_lscustom:getVehiclesPrices', function(vehicles)
Vehicles = vehicles
end)
end)
RegisterNetEvent('esx_lscustom:installMod')
AddEventHandler('esx_lscustom:installMod', function()
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
local NetId = NetworkGetNetworkIdFromEntity(vehicle)
myCar = ESX.Game.GetVehicleProperties(vehicle)
TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar, NetId)
end)
RegisterNetEvent('esx_lscustom:restoreMods', function(netId, props)
local xVehicle = NetworkGetEntityFromNetworkId(netId)
if props ~= nil then
if DoesEntityExist(xVehicle) then
ESX.Game.SetVehicleProperties(xVehicle, props)
end
end
end)
RegisterNetEvent('esx_lscustom:cancelInstallMod')
AddEventHandler('esx_lscustom:cancelInstallMod', function()
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if (GetPedInVehicleSeat(vehicle, -1) ~= PlayerPedId()) then
vehicle = GetPlayersLastVehicle(PlayerPedId())
end
ESX.Game.SetVehicleProperties(vehicle, myCar)
if not (myCar.modTurbo) then
ToggleVehicleMod(vehicle, 18, false)
end
if not (myCar.modXenon) then
ToggleVehicleMod(vehicle, 22, false)
end
if not (myCar.windowTint) then
SetVehicleWindowTint(vehicle, 0)
end
end)
AddEventHandler('onClientResourceStop', function(resource)
if resource == GetCurrentResourceName() then
if lsMenuIsShowed then
TriggerEvent('esx_lscustom:cancelInstallMod')
end
end
end)
AddEventHandler('onResourceStop', function(resource)
if resource == GetCurrentResourceName() then
if lsMenuIsShowed then
TriggerEvent('esx_lscustom:cancelInstallMod')
end
end
end)
function OpenLSMenu(elems, menuName, menuTitle, parent)
ESX.UI.Menu.Open('default', GetCurrentResourceName(), menuName, {
title = menuTitle,
align = 'top-left',
elements = elems
}, function(data, menu)
local isRimMod, found = false, false
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if data.current.modType == "modFrontWheels" then
isRimMod = true
end
if data.current.modType == "modBackWheels" then
isRimMod = true
end
for k, v in pairs(Config.Menus) do
if k == data.current.modType or isRimMod then
if data.current.label == TranslateCap('by_default') or string.match(data.current.label, TranslateCap('installed')) then
ESX.ShowNotification(TranslateCap('already_own', data.current.label))
myCar = ESX.Game.GetVehicleProperties(vehicle)
TriggerServerEvent('esx_lscustom:refreshOwnedVehicle', myCar, NetworkGetNetworkIdFromEntity(vehicle))
else
local vehiclePrice = 50000
for i = 1, #Vehicles, 1 do
if GetEntityModel(vehicle) == joaat(Vehicles[i].model) then
vehiclePrice = Vehicles[i].price
break
end
end
if isRimMod then
price = math.floor(vehiclePrice * data.current.price / 100)
TriggerServerEvent('esx_lscustom:buyMod', price)
elseif v.modType == 11 or v.modType == 12 or v.modType == 13 or v.modType == 15 or v.modType == 16 then
price = math.floor(vehiclePrice * v.price[data.current.modNum + 1] / 100)
TriggerServerEvent('esx_lscustom:buyMod', price)
elseif v.modType == 17 then
price = math.floor(vehiclePrice * v.price[1] / 100)
TriggerServerEvent('esx_lscustom:buyMod', price)
else
price = math.floor(vehiclePrice * v.price / 100)
TriggerServerEvent('esx_lscustom:buyMod', price)
end
end
menu.close()
found = true
break
end
end
if not found then
GetAction(data.current)
end
end, function(data, menu) -- on cancel
menu.close()
TriggerEvent('esx_lscustom:cancelInstallMod')
local playerPed = PlayerPedId()
local vehicle = GetVehiclePedIsIn(playerPed, false)
SetVehicleDoorsShut(vehicle, false)
if parent == nil then
lsMenuIsShowed = false
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
FreezeEntityPosition(vehicle, false)
TriggerServerEvent('esx_lscustom:stopModing', myCar.plate)
myCar = {}
end
end, function(data, menu) -- on change
UpdateMods(data.current)
end)
end
function UpdateMods(data)
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if data.modType then
local props = {}
if data.wheelType then
props['wheels'] = data.wheelType
if GetVehicleClass(vehicle) == 8 then -- Fix bug wheels for bikes.
props['modBackWheels'] = data.modNum
end
ESX.Game.SetVehicleProperties(vehicle, props)
props = {}
elseif data.modType == 'neonColor' then
if data.modNum[1] == 0 and data.modNum[2] == 0 and data.modNum[3] == 0 then
props['neonEnabled'] = {false, false, false, false}
else
props['neonEnabled'] = {true, true, true, true}
end
ESX.Game.SetVehicleProperties(vehicle, props)
props = {}
elseif data.modType == 'tyreSmokeColor' then
props['modSmokeEnabled'] = true
ESX.Game.SetVehicleProperties(vehicle, props)
props = {}
elseif data.modType == 'xenonColor' then
if data.modNum then
props['modXenon'] = true
else
props['modXenon'] = false
end
ESX.Game.SetVehicleProperties(vehicle, props)
props = {}
end
props[data.modType] = data.modNum
ESX.Game.SetVehicleProperties(vehicle, props)
end
end
function GetAction(data)
local elements = {}
local menuName = ''
local menuTitle = ''
local parent = nil
local playerPed = PlayerPedId()
local vehicle = GetVehiclePedIsIn(playerPed, false)
local currentMods = ESX.Game.GetVehicleProperties(vehicle)
if data.value == 'modSpeakers' or data.value == 'modTrunk' or data.value == 'modHydrolic' or data.value ==
'modEngineBlock' or data.value == 'modAirFilter' or data.value == 'modStruts' or data.value == 'modTank' then
SetVehicleDoorOpen(vehicle, 4, false)
SetVehicleDoorOpen(vehicle, 5, false)
elseif data.value == 'modDoorSpeaker' then
SetVehicleDoorOpen(vehicle, 0, false)
SetVehicleDoorOpen(vehicle, 1, false)
SetVehicleDoorOpen(vehicle, 2, false)
SetVehicleDoorOpen(vehicle, 3, false)
else
SetVehicleDoorsShut(vehicle, false)
end
local vehiclePrice = 50000
for i = 1, #Vehicles, 1 do
if GetEntityModel(vehicle) == joaat(Vehicles[i].model) then
vehiclePrice = Vehicles[i].price
break
end
end
for k, v in pairs(Config.Menus) do
if data.value == k then
menuName = k
menuTitle = v.label
parent = v.parent
if v.modType then
if v.modType == 22 or v.modType == 'xenonColor' then
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = k,
modNum = false
}
elseif v.modType == 'neonColor' or v.modType == 'tyreSmokeColor' then -- disable neon
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = k,
modNum = {0, 0, 0}
}
elseif v.modType == 'color1' or v.modType == 'color2' or v.modType == 'pearlescentColor' or v.modType ==
'wheelColor' then
local num = myCar[v.modType]
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = k,
modNum = num
}
elseif v.modType == 17 then
elements[#elements + 1] = {
label = " " .. TranslateCap('no_turbo'),
modType = k,
modNum = false
}
elseif v.modType == 23 then
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = "modFrontWheels",
modNum = -1,
wheelType = -1,
price = Config.DefaultWheelsPriceMultiplier
}
elseif v.modType == 24 then
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = "modBackWheels",
modNum = -1,
wheelType = -1,
price = Config.DefaultWheelsPriceMultiplier
}
else
elements[#elements + 1] = {
label = " " .. TranslateCap('by_default'),
modType = k,
modNum = -1
}
end
if v.modType == 14 then -- HORNS
for j = 0, 51, 1 do
local _label = ''
if j == currentMods.modHorns then
_label = GetHornName(j) .. ' - ' .. TranslateCap('installed') ..
''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = GetHornName(j) .. ' - $' .. price .. ' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = j
}
end
elseif v.modType == 'plateIndex' then -- PLATES
local maxJ = 5
if gameBuild >= 3095 then
maxJ = 12
end
for j = 0, maxJ, 1 do
local _label = ''
if j == currentMods.plateIndex then
_label = GetPlatesName(j) .. ' - ' ..
TranslateCap('installed') .. ''
else
local price = math.floor(vehiclePrice * v.price / 100)
_label = GetPlatesName(j) .. ' - $' .. price .. ' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = j
}
end
elseif v.modType == 22 then -- NEON
local _label = ''
if currentMods.modXenon then
_label = TranslateCap('neon') .. ' - ' .. TranslateCap('installed') .. ''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = TranslateCap('neon') .. ' - $' .. price .. ' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = true
}
elseif v.modType == 'xenonColor' then -- XENON COLOR
local xenonColors = GetXenonColors()
price = math.floor(vehiclePrice * v.price / 100)
for i = 1, #xenonColors, 1 do
elements[#elements + 1] = {
label = xenonColors[i].label .. ' - $' .. price .. '',
modType = k,
modNum = xenonColors[i].index
}
end
elseif v.modType == 'neonColor' or v.modType == 'tyreSmokeColor' then -- NEON & SMOKE COLOR
local neons = GetNeons()
price = math.floor(vehiclePrice * v.price / 100)
for i = 1, #neons, 1 do
elements[#elements + 1] = {
label = '' .. neons[i].label .. ' - $' .. price .. '',
modType = k,
modNum = {neons[i].r, neons[i].g, neons[i].b}
}
end
elseif v.modType == 'color1' or v.modType == 'color2' or v.modType == 'pearlescentColor' or v.modType ==
'wheelColor' then -- RESPRAYS
local colors = GetColors(data.color)
for j = 1, #colors, 1 do
local _label = ''
price = math.floor(vehiclePrice * v.price / 100)
_label = colors[j].label .. ' - $' .. price .. ' '
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = colors[j].index
}
end
elseif v.modType == 'windowTint' then -- WINDOWS TINT
for j = 1, 5, 1 do
local _label = ''
if j == currentMods.windowTint then
_label = GetWindowName(j) .. ' - ' .. TranslateCap('installed') ..
''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = GetWindowName(j) .. ' - $' .. price .. ' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = j
}
end
elseif v.modType == 23 then -- WHEELS RIM & TYPE
local props = {}
props['wheels'] = v.wheelType
ESX.Game.SetVehicleProperties(vehicle, props)
local modCount = GetNumVehicleMods(vehicle, v.modType)
for j = 0, modCount, 1 do
local modName = GetModTextLabel(vehicle, v.modType, j)
if modName then
local _label = ''
if j == currentMods.modFrontWheels then
_label = GetLabelText(modName) .. ' - ' ..
TranslateCap('installed') .. ''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = GetLabelText(modName) .. ' - $' .. price ..
' '
end
elements[#elements + 1] = {
label = _label,
modType = 'modFrontWheels',
modNum = j,
wheelType = v.wheelType,
price = v.price
}
end
end
elseif v.modType == 24 then -- MOTORCYCLES BACK WHEELS
local props = {}
props['wheels'] = v.wheelType
ESX.Game.SetVehicleProperties(vehicle, props)
local modCount = GetNumVehicleMods(vehicle, v.modType)
for j = 0, modCount, 1 do
local modName = GetModTextLabel(vehicle, v.modType, j)
if modName then
local _label = ''
if j == currentMods.modBackWheels then
_label = GetLabelText(modName) .. ' - ' ..
TranslateCap('installed') .. ''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = GetLabelText(modName) .. ' - $' .. price ..
' '
end
elements[#elements + 1] = {
label = _label,
modType = 'modBackWheels',
modNum = j,
wheelType = v.wheelType,
price = v.price
}
end
end
elseif v.modType == 11 or v.modType == 12 or v.modType == 13 or v.modType == 15 or v.modType == 16 then
SetVehicleModKit(vehicle, 0)
local modCount = GetNumVehicleMods(vehicle, v.modType) -- UPGRADES
for j = 0, modCount, 1 do
local _label = ''
if j == currentMods[k] then
_label =
TranslateCap('level', j + 1) .. ' - ' .. TranslateCap('installed') ..
''
else
price = math.floor(vehiclePrice * v.price[j + 1] / 100)
_label = TranslateCap('level', j + 1) .. ' - $' .. price .. ' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = j
}
if j == modCount - 1 then
break
end
end
elseif v.modType == 17 then -- TURBO
local _label = ''
if currentMods[k] then
_label = 'Turbo - ' .. TranslateCap('installed') .. ''
else
_label =
'Turbo - $' .. math.floor(vehiclePrice * v.price[1] / 100) ..
' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = true
}
else
local modCount = GetNumVehicleMods(vehicle, v.modType) -- BODYPARTS
for j = 0, modCount, 1 do
local modName = GetModTextLabel(vehicle, v.modType, j)
if modName then
local _label = ''
if j == currentMods[k] then
_label = GetLabelText(modName) .. ' - ' ..
TranslateCap('installed') .. ''
else
price = math.floor(vehiclePrice * v.price / 100)
_label = GetLabelText(modName) .. ' - $' .. price ..
' '
end
elements[#elements + 1] = {
label = _label,
modType = k,
modNum = j
}
end
end
end
else
if data.value == 'primaryRespray' or data.value == 'secondaryRespray' or data.value ==
'pearlescentRespray' or data.value == 'modFrontWheelsColor' then
for i = 1, #Config.Colors, 1 do
if data.value == 'primaryRespray' then
elements[#elements + 1] = {
label = Config.Colors[i].label,
value = 'color1',
color = Config.Colors[i].value
}
elseif data.value == 'secondaryRespray' then
elements[#elements + 1] = {
label = Config.Colors[i].label,
value = 'color2',
color = Config.Colors[i].value
}
elseif data.value == 'pearlescentRespray' then
elements[#elements + 1] = {
label = Config.Colors[i].label,
value = 'pearlescentColor',
color = Config.Colors[i].value
}
elseif data.value == 'modFrontWheelsColor' then
elements[#elements + 1] = {
label = Config.Colors[i].label,
value = 'wheelColor',
color = Config.Colors[i].value
}
end
end
else
for l, w in pairs(v) do
if l ~= 'label' and l ~= 'parent' then
elements[#elements + 1] = {
label = w,
value = l
}
end
end
end
end
break
end
end
table.sort(elements, function(a, b)
return a.label < b.label
end)
OpenLSMenu(elements, menuName, menuTitle, parent)
end
-- Blips
CreateThread(function()
for k, v in pairs(Config.Zones) do
local blip = AddBlipForCoord(v.Pos.x, v.Pos.y, v.Pos.z)
SetBlipSprite(blip, 72)
SetBlipScale(blip, 0.8)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName(v.Name)
EndTextCommandSetBlipName(blip)
end
end)
-- Activate menu when player is inside marker
CreateThread(function()
while true do
local Sleep = 1500
local Near = false
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
local coords = GetEntityCoords(playerPed)
local currentZone, zone, lastZone
if (ESX.PlayerData.job and ESX.PlayerData.job.name == 'mechanic') or not Config.IsMechanicJobOnly then
for k, v in pairs(Config.Zones) do
if #(coords - v.Pos) < Config.DrawDistance then
Near = true
Sleep = 0
if not lsMenuIsShowed then
if not HintDisplayed then
HintDisplayed = true
ESX.TextUI(v.Hint)
end
if IsControlJustReleased(0, 38) then
lsMenuIsShowed = true
local vehicle = GetVehiclePedIsIn(playerPed, false)
FreezeEntityPosition(vehicle, true)
myCar = ESX.Game.GetVehicleProperties(vehicle)
local netId = NetworkGetNetworkIdFromEntity(vehicle)
TriggerServerEvent('esx_lscustom:startModing', myCar, netId)
ESX.UI.Menu.CloseAll()
GetAction({
value = 'main'
})
-- Prevent Free Tunning Bug
CreateThread(function()
while true do
local Sleep = 1000
if lsMenuIsShowed then
Sleep = 0
DisableControlAction(2, 288, true)
DisableControlAction(2, 289, true)
DisableControlAction(2, 170, true)
DisableControlAction(2, 167, true)
DisableControlAction(2, 168, true)
DisableControlAction(2, 23, true)
DisableControlAction(0, 75, true) -- Disable exit vehicle
DisableControlAction(27, 75, true) -- Disable exit vehicle
end
Wait(Sleep)
end
end)
end
end
end
end
if not Near and HintDisplayed then
HintDisplayed = false
ESX.HideUI()
end
end
end
Wait(Sleep)
end
end)