diff --git a/resources/[carscripts]/lc_fuel/README.md b/resources/[carscripts]/lc_fuel/README.md
index c7717a525..9d55eaf4e 100644
--- a/resources/[carscripts]/lc_fuel/README.md
+++ b/resources/[carscripts]/lc_fuel/README.md
@@ -1,16 +1,16 @@
-# LC_Fuel - FiveM
-
-## About
-A fuel system that adds realism and depth to vehicle management. Whether your players drive gas-powered cars, diesel, or electric vehicles, this script ensures an immersive refueling experience.
-
-## Installation
-Install steps available on our docs: [Installation - LC Fuel](https://docs.lixeirocharmoso.com/lc_fuel/installation)
-
-## Exports
-Exports available in our docs: [Exports - LC Fuel](https://docs.lixeirocharmoso.com/lc_fuel/exports)
-
-## Our links
-- Discord: [https://discord.gg/U5YDgbh](https://discord.gg/U5YDgbh)
-- Tebex: [https://lixeirocharmoso.tebex.io](https://lixeirocharmoso.tebex.io)
-- Docs: [https://docs.lixeirocharmoso.com](https://docs.lixeirocharmoso.com/lc_fuel)
+# LC_Fuel - FiveM
+
+## About
+A fuel system that adds realism and depth to vehicle management. Whether your players drive gas-powered cars, diesel, or electric vehicles, this script ensures an immersive refueling experience.
+
+## Installation
+Install steps available on our docs: [Installation - LC Fuel](https://docs.lixeirocharmoso.com/lc_fuel/installation)
+
+## Exports
+Exports available in our docs: [Exports - LC Fuel](https://docs.lixeirocharmoso.com/lc_fuel/exports)
+
+## Our links
+- Discord: [https://discord.gg/U5YDgbh](https://discord.gg/U5YDgbh)
+- Tebex: [https://lixeirocharmoso.tebex.io](https://lixeirocharmoso.tebex.io)
+- Docs: [https://docs.lixeirocharmoso.com](https://docs.lixeirocharmoso.com/lc_fuel)
- Showcase: [https://youtu.be/M6__IeCwxH8](https://youtu.be/M6__IeCwxH8)
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client.lua b/resources/[carscripts]/lc_fuel/client/client.lua
index 04fb3f3eb..630b2b034 100644
--- a/resources/[carscripts]/lc_fuel/client/client.lua
+++ b/resources/[carscripts]/lc_fuel/client/client.lua
@@ -1,1598 +1,1604 @@
--- Shared variables
-Utils = Utils or exports['lc_utils']:GetUtils()
-cachedTranslations = {}
-mainUiOpen = false
-
-fuelNozzle = 0
-fuelRope = 0
-currentPump = 0
-JERRY_CAN_HASH = 883325847
-
--- Fuel chart variables
-isFuelConsumptionChartOpen = false
-isRecording = true
-
--- Local variables
-local fuelDecor = "_FUEL_LEVEL"
-local currentConsumption = 0.0
-local fuelSynced = true
-local closestVehicleToPump = 0
-local isNuiVariablesLoaded = false
-
-DecorRegister(fuelDecor, 1)
--- Check if it actually registered
-if DecorIsRegisteredAsType(fuelDecor, 1) then
- print("[Fuel Script] SUCCESS: fuelDecor was registered successfully!")
-else
- print("[Fuel Script] ERROR: fuelDecor registration failed!")
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Threads
------------------------------------------------------------------------------------------------------------------------------------------
-
--- Thread to handle the fuel consumption
-function createFuelConsumptionThread()
- CreateThread(function()
- local currentVehicle = nil
- local currentVehicleFuelType = "default" -- default while the callback loads
- DecorRegister(fuelDecor, 1)
- while true do
- Wait(1000)
- local ped = PlayerPedId()
- if IsPedInAnyVehicle(ped, false) then
- local vehicle = GetVehiclePedIsIn(ped, false)
- if GetPedInVehicleSeat(vehicle, -1) == ped and not IsVehicleBlacklisted(vehicle) then
- if currentVehicle == nil or currentVehicle ~= vehicle then
- currentVehicle = vehicle
- currentVehicleFuelType = getVehicleFuelTypeFromServer(vehicle)
- fuelSynced = false
- end
- HandleFuelConsumption(vehicle, currentVehicleFuelType)
- end
- else
- if isFuelConsumptionChartOpen then
- closeFuelConsumptionChartUI()
- end
- currentVehicleFuelType = "default"
- currentVehicle = nil
- fuelSynced = false
- end
- end
- end)
-end
-
-function HandleFuelConsumption(vehicle, fuelType)
- -- If no decorator exists, set a random fuel %
- if not DecorExistOn(vehicle, fuelDecor) then
- SetFuel(vehicle, math.random(200, 800) / 10)
- elseif not fuelSynced then
- -- Sync once
- SetFuel(vehicle, GetFuel(vehicle))
- fuelSynced = true
- end
-
- -- If engine is off, do nothing
- if not GetIsVehicleEngineRunning(vehicle) then
- return
- end
-
- -- Turns engine off if have no fuel
- local currentFuelLevel = GetVehicleFuelLevel(vehicle)
- if currentFuelLevel <= 0.0 then
- SetVehicleEngineOn(vehicle, false, true, false)
- return
- end
-
- -- Get the vehicle's actual tank size in liters
- local tankSize = getVehicleTankSize(vehicle)
-
- -- Base consumption from config and RPM
- currentConsumption = Config.FuelUsage[Utils.Math.round(GetVehicleCurrentRpm(vehicle), 1)] * (Config.FuelConsumptionPerClass[GetVehicleClass(vehicle)] or 1.0) * (Config.FuelConsumptionPerFuelType[fuelType] or 1.0) / 10
-
- -- Scale consumption according to tank size.
- -- A smaller tank will lose percentage faster; a bigger tank slower.
- local scaledConsumption = currentConsumption * (100 / tankSize)
-
- -- Subtract from the current fuel %
- local newFuelLevel = currentFuelLevel - scaledConsumption
-
- -- Write the new fuel % back
- SetFuel(vehicle, newFuelLevel)
-
- -- Store data for chart
- if Config.FuelConsumptionChart.enabled then
- storeDataForChart(vehicle, newFuelLevel, currentConsumption)
- end
-
- validateDieselFuelMismatch(vehicle, fuelType)
-end
-
-function validateDieselFuelMismatch(vehicle, fuelType)
- if (fuelType == "diesel" and not IsVehicleDiesel(vehicle)) or (fuelType ~= "diesel" and IsVehicleDiesel(vehicle)) then
- SetTimeout(5000, function()
- if IsVehicleDriveable(vehicle, false) then
- SetVehicleEngineHealth(vehicle, 0.0)
- SetVehicleUndriveable(vehicle, true)
- exports['lc_utils']:notify("error", Utils.translate("vehicle_wrong_fuel"))
- end
- end)
- end
-end
-
-function createDebugNozzleOffsetThread()
- CreateThread(function()
- while true do
- local vehicle = GetVehiclePlayerIsLookingAt()
- if not vehicle or not DoesEntityExist(vehicle) then
- Wait(2)
- goto continue -- Skip if no valid vehicle found
- end
-
- local hit, hitCoords = GetLookAtHitCoords()
- if hit and DoesEntityExist(vehicle) then
- local offset = GetNozzleOffset(vehicle, hitCoords)
-
- if offset then
- local vehCoords = GetEntityCoords(vehicle)
-
- -- Get vehicle's axis vectors
- local forwardVector, rightVector, upVector = GetEntityMatrix(vehicle)
-
- -- Direction from vehicle to hit point
- local directionToHit = hitCoords - vehCoords
- directionToHit = directionToHit / #(directionToHit) -- normalize
-
- -- Dot product with right vector
- local side = rightVector.x * directionToHit.x + rightVector.y * directionToHit.y + rightVector.z * directionToHit.z
-
- -- Adjust offset.right
- if side > 0 then
- -- hit is on the right side
- offset.right = offset.right + 0.07
- else
- -- hit is on the left side
- offset.right = offset.right - 0.07
- end
-
- local boneWorldPos = GetVehicleCapPos(vehicle)
-
- -- local forwardVector, rightVector, upVector, _ = GetEntityMatrix(vehicle)
-
- -- Scale vectors by the local offset
- local forwardOffset = forwardVector * offset.forward
- local rightOffset = rightVector * offset.right
- local upOffset = upVector * offset.up
-
- -- Final world position of the nozzle point
- local finalWorldPos = vector3(
- boneWorldPos.x + forwardOffset.x + rightOffset.x + upOffset.x,
- boneWorldPos.y + forwardOffset.y + rightOffset.y + upOffset.y,
- boneWorldPos.z + forwardOffset.z + rightOffset.z + upOffset.z
- )
-
- -- Draw a small marker at the computed position
- DrawMarker(28, finalWorldPos.x, finalWorldPos.y, finalWorldPos.z + 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03, 0.03, 0.03, 255, 0, 0, 180, false, true, 2, nil, nil, false)
-
- if IsControlJustPressed(0,38) then
- local model = GetEntityModel(vehicle)
- local modelName = GetDisplayNameFromVehicleModel(model):lower()
-
- local zRotation = side > 0 and 180 or 0
-
- local clipboardText = string.format(
- '["%s"] = { distance = 1.3, nozzleOffset = { forward = %.2f, right = %.2f, up = %.2f }, nozzleRotation = { x = 0, y = 0, z = %d } },',
- modelName,
- offset.forward, offset.right, offset.up,
- zRotation
- )
-
- SendNUIMessage({
- type = "copyToClipboard",
- text = clipboardText
- })
-
- exports['lc_utils']:notify("success", "Copied to clipboard: " .. clipboardText)
- exports['lc_utils']:notify("warning", "Make sure the vehicle spawn name is correct. You may need to manually fine-tune the offset and rotation.")
- end
- end
- end
- Wait(2)
- ::continue::
- end
- end)
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- UI
------------------------------------------------------------------------------------------------------------------------------------------
-
-function clientOpenUI(pump, pumpModel, isElectricPump)
- currentPump = pump
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
-
- closestVehicleToPump = GetClosestVehicle(playerCoords)
- local isElectricVehicle = IsVehicleElectric(closestVehicleToPump)
- if not (isElectricVehicle and isElectricPump) and not (not isElectricVehicle and not isElectricPump) then
- -- Reset the near vehicle to 0 when it does not match the pump type (only allows electric vehicle in electric chargers and gas vehicles in gas pumps)
- closestVehicleToPump = 0
- end
-
- pumpLocation = nil
-
- if closestVehicleToPump and #(playerCoords - GetEntityCoords(closestVehicleToPump)) < 5 then
- -- Load the nearest vehicle fuel and plate (fuel type)
- local vehicleFuel = GetFuel(closestVehicleToPump)
- local vehiclePlate = GetVehicleNumberPlateText(closestVehicleToPump)
- local vehicleTankSize = getVehicleTankSize(closestVehicleToPump)
- local vehicleDisplayFuelAmount = getVehicleDisplayFuelAmount(vehicleFuel, vehicleTankSize)
- TriggerServerEvent("lc_fuel:serverOpenUI", isElectricPump, pumpModel, vehicleDisplayFuelAmount, vehicleTankSize, vehiclePlate)
- else
- -- Allow the user to open the UI even without vehicles nearby
- TriggerServerEvent("lc_fuel:serverOpenUI", isElectricPump, pumpModel)
- end
-end
-
-function loadNuiVariables()
- if isNuiVariablesLoaded then
- return
- end
-
- -- Load NUI variables
- SendNUIMessage({
- utils = { config = Utils.Config, lang = Utils.Lang },
- resourceName = GetCurrentResourceName()
- })
-
- local maxIterations = 100 -- Maximum number of iterations (100 * 100ms = 10 seconds)
- local iterations = 0
-
- while not isNuiVariablesLoaded do
- Wait(100)
- iterations = iterations + 1
-
- if iterations >= maxIterations then
- print("Error: Timeout while loading NUI variables after " .. iterations .. " attempts.")
- return
- end
- end
-end
-
-
-RegisterNetEvent('lc_fuel:clientOpenUI')
-AddEventHandler('lc_fuel:clientOpenUI', function(data)
- loadNuiVariables()
- data.currentFuelType = dealWithDefaultFuelType(closestVehicleToPump, data.currentFuelType)
- SendNUIMessage({
- openMainUI = true,
- data = data
- })
- mainUiOpen = true
- TriggerScreenblurFadeIn(1000)
- FreezeEntityPosition(PlayerPedId(), true)
- SetNuiFocus(true,true)
-end)
-
-RegisterNUICallback('post', function(body, cb)
- if cooldown == nil then
- cooldown = true
-
- if body.event == "close" then
- closeUI()
- elseif body.event == "closeFuelConsumptionChartUI" then
- closeFuelConsumptionChartUI()
- elseif body.event == "removeFocusFuelConsumptionChartUI" then
- SetNuiFocus(false,false)
- elseif body.event == "startRecordingGraph" then
- isRecording = true
- elseif body.event == "stopRecordingGraph" then
- isRecording = false
- elseif body.event == "notify" then
- exports['lc_utils']:notify(body.data.type,body.data.msg)
- elseif body.event == "changeVehicleFuelType" then
- changeVehicleFuelType(closestVehicleToPump, body.data.selectedFuelType)
- else
- TriggerServerEvent('lc_fuel:'..body.event,body.data)
- end
- cb(200)
-
- SetTimeout(5,function()
- cooldown = nil
- end)
- end
-end)
-
-RegisterNUICallback('setNuiVariablesLoaded', function(body, cb)
- isNuiVariablesLoaded = true
- cb(200)
-end)
-
-function closeUI()
- mainUiOpen = false
- FreezeEntityPosition(PlayerPedId(), false)
- TriggerScreenblurFadeOut(1000)
- SetNuiFocus(false,false)
- SendNUIMessage({ hideMainUI = true })
-end
-
-RegisterNetEvent('lc_fuel:closeUI')
-AddEventHandler('lc_fuel:closeUI', function()
- closeUI()
-end)
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Exports
------------------------------------------------------------------------------------------------------------------------------------------
-
-function GetFuel(vehicle)
- if not DoesEntityExist(vehicle) then
- warn(("[GetFuel] Vehicle entity does not exist. Received: %s. This is usually caused by a misconfiguration in the export."):format(tostring(vehicle)))
- return 0
- end
- return DecorGetFloat(vehicle, fuelDecor)
-end
-exports('GetFuel', GetFuel)
-
-function SetFuel(vehicle, fuel)
- if not DoesEntityExist(vehicle) then
- warn(("[SetFuel] Vehicle entity does not exist. Received: %s. This is usually caused by a misconfiguration in the export."):format(tostring(vehicle)))
- return
- end
-
- if type(fuel) ~= "number" then
- warn(("[SetFuel] Invalid fuel value received: %s. Fuel must be a number between 0 and 100."):format(tostring(fuel)))
- return
- end
-
- -- Normalize the fuel values if received negative values or higher than 100
- fuel = math.max(0.0, math.min(fuel, 100.0))
-
- SetVehicleFuelLevel(vehicle, fuel + 0.0)
- DecorSetFloat(vehicle, fuelDecor, GetVehicleFuelLevel(vehicle))
-end
-exports('SetFuel', SetFuel)
-
--- Just another way to call the exports in case someone does it like this...
-function getFuel(vehicle)
- return GetFuel(vehicle)
-end
-exports('getFuel', getFuel)
-
-function setFuel(vehicle, fuel)
- SetFuel(vehicle, fuel)
-end
-exports('setFuel', setFuel)
-
--- Alias LegacyFuel's exports to point to our lc_fuel functions:
-AddEventHandler('__cfx_export_LegacyFuel_SetFuel', function(setCB)
- -- Redirect LegacyFuel:SetFuel to use lc_fuel's SetFuel function
- setCB(SetFuel)
-end)
-
-AddEventHandler('__cfx_export_LegacyFuel_GetFuel', function(setCB)
- -- Redirect LegacyFuel:GetFuel to use lc_fuel's GetFuel function
- setCB(GetFuel)
-end)
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Utils
------------------------------------------------------------------------------------------------------------------------------------------
-
-function getVehicleFuelTypeFromServer(vehicle)
- local returnFuelType = nil
-
- Utils.Callback.TriggerServerCallback('lc_fuel:getVehicleFuelType', function(fuelType)
- returnFuelType = dealWithDefaultFuelType(vehicle, fuelType)
- end, GetVehicleNumberPlateText(vehicle))
-
- while returnFuelType == nil do
- Wait(10)
- end
- return returnFuelType
-end
-
-function dealWithDefaultFuelType(vehicle, fuelType)
- -- Define if the vehicle is diesel or gasoline for the ones that have never been refueled
- if fuelType == "default" then
- if IsVehicleDiesel(vehicle) then
- fuelType = "diesel"
- else
- fuelType = "regular"
- end
- end
- return fuelType
-end
-
-function changeVehicleFuelType(vehicle, fuelType)
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
- if vehicle and #(playerCoords - GetEntityCoords(vehicle)) < 5 then
- SetFuel(vehicle, 0.0)
- exports['lc_utils']:notify("info",Utils.translate("vehicle_tank_emptied"))
- TriggerServerEvent("lc_fuel:setVehicleFuelType", GetVehicleNumberPlateText(vehicle), fuelType)
- else
- exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
- end
-end
-
-function getVehicleDisplayFuelAmount(currentFuel, tankSize)
- local displayFuelAmount = currentFuel * tankSize / 100
- return displayFuelAmount
-end
-
-function getVehicleTankSize(vehicle)
- local vehicleHash = GetEntityModel(vehicle)
- if Config.FuelTankSize.perVehicleHash[vehicleHash] then
- return Config.FuelTankSize.perVehicleHash[vehicleHash]
- end
- return Config.FuelTankSize.perClass[GetVehicleClass(vehicle)] or 100
-end
-
-function GetPumpOffset(pump)
- local heightOffset = { forward = 0.0, right = 0.0, up = 2.1 }
- local pumpModel = GetEntityModel(pump)
-
- for _, v in pairs(Config.Electric.chargersProps) do
- if pumpModel == joaat(v.prop) then
- heightOffset = v.ropeOffset
- end
- end
-
- for _, v in pairs(Config.GasPumpProps) do
- if pumpModel == joaat(v.prop) then
- heightOffset = v.ropeOffset
- end
- end
-
- return heightOffset
-end
-
-function CreateRopeToPump(pumpCoords)
- local offset = GetPumpOffset(currentPump)
-
- RopeLoadTextures()
- while not RopeAreTexturesLoaded() do
- Wait(0)
- end
-
- local forwardVector, rightVector, upVector, _ = GetEntityMatrix(currentPump)
-
- -- Adjust the offsets
- local forwardOffset = forwardVector * offset.forward
- local rightoffset = rightVector * offset.right
- local upOffset = upVector * offset.up
- local finalOffset = forwardOffset + rightoffset + upOffset
-
- local ropeObj = AddRope(pumpCoords.x + finalOffset.x, pumpCoords.y + finalOffset.y, pumpCoords.z + finalOffset.z, 0.0, 0.0, 0.0, 4.0, 1, 10.0, 0.0, 1.0, false, false, false, 1.0, true)
- while not ropeObj do
- Wait(0)
- end
- ActivatePhysics(ropeObj)
- Wait(100)
-
- local nozzlePos = GetOffsetFromEntityInWorldCoords(fuelNozzle, 0.0, -0.033, -0.195)
- ---@diagnostic disable-next-line: param-type-mismatch
- AttachEntitiesToRope(ropeObj, currentPump, fuelNozzle, pumpCoords.x + finalOffset.x, pumpCoords.y + finalOffset.y, pumpCoords.z + finalOffset.z, nozzlePos.x, nozzlePos.y, nozzlePos.z, 30.0, false, false, nil, nil)
- return ropeObj
-end
-
-function GetVehicles()
- return GetGamePool('CVehicle')
-end
-
-function GetClosestVehicle(coords, modelFilter)
- return GetClosestEntity(GetVehicles(), false, coords, modelFilter)
-end
-
-function GetClosestEntity(entities, isPlayerEntities, coords, modelFilter)
- local closestEntity, closestEntityDistance, filteredEntities = -1, -1, nil
-
- if coords then
- coords = vector3(coords.x, coords.y, coords.z)
- else
- local playerPed = PlayerPedId()
- coords = GetEntityCoords(playerPed)
- end
-
- if modelFilter then
- filteredEntities = {}
-
- for _, entity in pairs(entities) do
- if modelFilter[GetEntityModel(entity)] then
- filteredEntities[#filteredEntities + 1] = entity
- end
- end
- end
-
- for k, entity in pairs(filteredEntities or entities) do
- local distance = #(coords - GetEntityCoords(entity))
-
- if closestEntityDistance == -1 or distance < closestEntityDistance then
- closestEntity, closestEntityDistance = isPlayerEntities and k or entity, distance
- end
- end
-
- return closestEntity, closestEntityDistance
-end
-
-function GetVehicleCapPos(vehicle)
- local closestCapPos
- local tanks = vehicleCapBoneList()
- for _, v in pairs(tanks) do
- local vehicleTank = GetEntityBoneIndexByName(vehicle, v)
- if vehicleTank ~= -1 then
- closestCapPos = GetWorldPositionOfEntityBone(vehicle, vehicleTank)
- break
- end
- end
- return closestCapPos
-end
-
-function Round(num, numDecimalPlaces)
- error("Do not use this")
-end
-
-function IsVehicleBlacklisted(vehicle)
- if vehicle and vehicle ~= 0 then
- local vehicleHash = GetEntityModel(vehicle)
- -- Blacklist electric vehicles if electric recharge is disabled
- if not Config.Electric.enabled and IsVehicleElectric(vehicle) then
- return true
- end
-
- -- Check if the vehicle is in the blacklist
- if Config.BlacklistedVehiclesHash[vehicleHash] then
- return true
- end
- return false
- end
- return true
-end
-
-function IsVehicleDiesel(vehicle)
- if vehicle and vehicle ~= 0 then
- local vehicleHash = GetEntityModel(vehicle)
- -- Check if the vehicle is in the diesel list
- if Config.DieselVehiclesHash[vehicleHash] then
- return true
- end
- end
- return false
-end
-
-function IsVehicleElectric(vehicle)
- if vehicle and vehicle ~= 0 then
- local vehicleHash = GetEntityModel(vehicle)
- -- Check if the vehicle is in the diesel list
- if Config.Electric.vehiclesListHash[vehicleHash] then
- return true
- end
- end
- return false
-end
-
-function GetClosestPump(coords, isElectric)
- local pump = nil
- local currentPumpModel = nil
- local pumpList = isElectric and Config.Electric.chargersProps or Config.GasPumpProps
-
- for i = 1, #pumpList do
- currentPumpModel = pumpList[i].prop
- pump = GetClosestObjectOfType(coords.x, coords.y, coords.z, 2.5, joaat(currentPumpModel), true, true, true)
- if pump ~= 0 then return pump, currentPumpModel end
- end
-
- return nil, nil
-end
-
-function createBlips()
- if Config.Blips.onlyShowNearestBlip then
- Citizen.CreateThread(function()
- local currentBlip = 0
- local currentBlipIndex = 0
-
- while true do
- local coords = GetEntityCoords(PlayerPedId())
- local closestBlipDistance = math.maxinteger
- local closestBlipCoords
- local closestBlipId
-
- for blipId, blipCoord in pairs(Config.Blips.locations) do
- local distanceToBlip = #(coords - blipCoord)
-
- if distanceToBlip < closestBlipDistance then
- closestBlipDistance = distanceToBlip
- closestBlipCoords = blipCoord
- closestBlipId = blipId
- end
- end
-
- if currentBlipIndex ~= closestBlipId then
- if DoesBlipExist(currentBlip) then
- Utils.Blips.removeBlip(currentBlip)
- end
-
- if closestBlipCoords then
- currentBlip = Utils.Blips.createBlipForCoords(closestBlipCoords.x,closestBlipCoords.y,closestBlipCoords.z,Config.Blips.blipId,Config.Blips.color,Utils.translate('blip_text'),Config.Blips.scale,false)
- end
-
- currentBlipIndex = closestBlipId
- end
-
- Citizen.Wait(5000)
- end
- end)
- else
- local text = Utils.translate('blip_text')
- for _, blipCoords in pairs(Config.Blips.locations) do
- Utils.Blips.createBlipForCoords(blipCoords.x,blipCoords.y,blipCoords.z,Config.Blips.blipId,Config.Blips.color,text,Config.Blips.scale,false)
- end
- end
-end
-
-function convertConfigVehiclesDisplayNameToHash()
- Config.BlacklistedVehiclesHash = {}
- for _, value in pairs(Config.BlacklistedVehicles) do
- Config.BlacklistedVehiclesHash[joaat(value)] = true
- end
- Config.Electric.vehiclesListHash = {}
- for _, value in pairs(Config.Electric.vehiclesList) do
- Config.Electric.vehiclesListHash[joaat(value)] = true
- end
- Config.DieselVehiclesHash = {}
- for _, value in pairs(Config.DieselVehicles) do
- Config.DieselVehiclesHash[joaat(value)] = true
- end
- Config.FuelTankSize.perVehicleHash = {}
- for key, value in pairs(Config.FuelTankSize.perVehicle) do
- Config.FuelTankSize.perVehicleHash[joaat(key)] = value
- end
- Config.CustomVehicleParametersHash = {}
- Utils.Table.deepMerge(Config.HiddenCustomVehicleParameters, Config.CustomVehicleParameters)
- for key, value in pairs(Config.HiddenCustomVehicleParameters) do
- Config.CustomVehicleParametersHash[joaat(key)] = value
- end
- Config.CustomVehicleParametersHash.default = Config.CustomVehicleParameters.default -- Adds back the default
-end
-
-RegisterNetEvent('lc_fuel:Notify')
-AddEventHandler('lc_fuel:Notify', function(type,message)
- exports['lc_utils']:notify(type,message)
-end)
-
-Citizen.CreateThread(function()
- Wait(1000)
- SetNuiFocus(false,false)
- SetNuiFocusKeepInput(false)
- FreezeEntityPosition(PlayerPedId(), false)
-
- Utils.loadLanguageFile(Lang)
-
- cachedTranslations = {
- open_refuel = Utils.translate('markers.open_refuel'),
- open_recharge = Utils.translate('markers.open_recharge'),
- interact_with_vehicle = Utils.translate('markers.interact_with_vehicle'),
- return_nozzle = Utils.translate('markers.return_nozzle'),
- }
-
- convertConfigVehiclesDisplayNameToHash()
-
- if Config.Blips and Config.Blips.enabled then
- createBlips()
- end
-
- -- Gas
- if Utils.Config.custom_scripts_compatibility.target == "disabled" then
- createGasMarkersThread()
- else
- createGasTargetsThread()
- end
- createCustomPumpModelsThread()
-
- -- Electrics
- if Config.Electric.enabled then
- CreateThread(function()
- createElectricZones()
-
- if Utils.Config.custom_scripts_compatibility.target == "disabled" then
- createElectricMarkersThread()
- else
- createElectricTargetsThread()
- end
- end)
- end
-
- -- Refuel
- if Utils.Config.custom_scripts_compatibility.target ~= "disabled" then
- createTargetForVehicleIteraction()
- end
-
- -- Other threads
- createFuelConsumptionThread()
- if Config.JerryCan.enabled and Utils.Config.custom_scripts_compatibility.target == "disabled" then
- createJerryCanThread()
- end
-
- if Config.DebugNozzleOffset then
- createDebugNozzleOffsetThread()
- end
-end)
-
--- Debug nozzle offset functions
-function GetVehiclePlayerIsLookingAt()
- local playerPed = PlayerPedId()
- local camCoords = GetGameplayCamCoord()
- local camRot = GetGameplayCamRot(2)
- local direction = RotationToDirection(camRot)
- local maxDistance = 10.0
-
- local destCoords = camCoords + direction * maxDistance
- local rayHandle = StartShapeTestRay(camCoords.x, camCoords.y, camCoords.z, destCoords.x, destCoords.y, destCoords.z, 10, playerPed, 0)
- local _, hit, endCoords, _, entityHit = GetShapeTestResult(rayHandle)
-
- if hit == 1 and IsEntityAVehicle(entityHit) then
- return entityHit
- end
- return nil
-end
-
-function GetLookAtHitCoords()
- local playerPed = PlayerPedId()
- local camCoords = GetGameplayCamCoord()
- local camRot = GetGameplayCamRot(2)
- local direction = RotationToDirection(camRot)
-
- local endCoords = vec3(
- camCoords.x + direction.x * 10.0,
- camCoords.y + direction.y * 10.0,
- camCoords.z + direction.z * 10.0
- )
-
- local rayHandle = StartShapeTestRay(camCoords.x, camCoords.y, camCoords.z, endCoords.x, endCoords.y, endCoords.z, -1, playerPed, 0)
- local _, hit, hitCoords = GetShapeTestResult(rayHandle)
- return hit, hitCoords
-end
-
-function RotationToDirection(rot)
- local z = math.rad(rot.z)
- local x = math.rad(rot.x)
- local cosX = math.cos(x)
-
- return vec3(
- -math.sin(z) * cosX,
- math.cos(z) * cosX,
- math.sin(x)
- )
-end
-
--- Gets the offset from 'petrolcap' to the point you're looking at
-function GetNozzleOffset(vehicle, hitCoords)
- -- World position of the bone
- local boneWorldPos = GetVehicleCapPos(vehicle)
-
- -- Directional vector from bone to hit point
- local direction = {
- x = hitCoords.x - boneWorldPos.x,
- y = hitCoords.y - boneWorldPos.y,
- z = hitCoords.z - boneWorldPos.z
- }
-
- -- Convert direction vector to vehicle-local offset
- local forwardVector, rightVector, upVector, _ = GetEntityMatrix(vehicle)
-
- local offset = {
- right = direction.x * rightVector.x + direction.y * rightVector.y + direction.z * rightVector.z,
- forward = direction.x * forwardVector.x + direction.y * forwardVector.y + direction.z * forwardVector.z,
- up = direction.x * upVector.x + direction.y * upVector.y + direction.z * upVector.z
- }
-
- return offset
-end
-
-if Config.EnableHUD then
- local function DrawAdvancedText(x,y ,w,h,sc, text, r,g,b,a,font,jus)
- SetTextFont(font)
- SetTextProportional(false)
- SetTextScale(sc, sc)
- SetTextJustification(jus)
- SetTextColour(r, g, b, a)
- SetTextDropShadow()
- SetTextEdge(1, 0, 0, 0, 255)
- SetTextDropShadow()
- SetTextOutline()
- SetTextEntry("STRING")
- AddTextComponentString(text)
- DrawText(x - 0.1+w, y - 0.02+h)
- end
-
- local mph = "0"
- local kmh = "0"
- local fuel = "0"
- local displayHud = false
-
- local x = 0.01135
- local y = 0.002
-
- Citizen.CreateThread(function()
- while true do
- local ped = PlayerPedId()
-
- if IsPedInAnyVehicle(ped, false) then
- local vehicle = GetVehiclePedIsIn(ped, false)
- local speed = GetEntitySpeed(vehicle)
-
- mph = tostring(math.ceil(speed * 2.236936))
- kmh = tostring(math.ceil(speed * 3.6))
- fuel = tostring(Utils.Math.round(GetVehicleFuelLevel(vehicle),2))
-
- displayHud = true
- else
- displayHud = false
-
- Citizen.Wait(500)
- end
-
- Citizen.Wait(50)
- end
- end)
-
- Citizen.CreateThread(function()
- while true do
- if displayHud then
- DrawAdvancedText(0.130 - x, 0.77 - y, 0.005, 0.0028, 0.6, mph, 255, 255, 255, 255, 6, 1)
- DrawAdvancedText(0.174 - x, 0.77 - y, 0.005, 0.0028, 0.6, kmh, 255, 255, 255, 255, 6, 1)
- DrawAdvancedText(0.2155 - x, 0.77 - y, 0.005, 0.0028, 0.6, fuel, 255, 255, 255, 255, 6, 1)
- DrawAdvancedText(0.2615 - x, 0.77 - y, 0.005, 0.0028, 0.6, tostring(currentConsumption), 255, 255, 255, 255, 6, 1)
- DrawAdvancedText(0.145 - x, 0.7765 - y, 0.005, 0.0028, 0.4, "mp/h km/h Fuel Consumption", 255, 255, 255, 255, 6, 1)
- else
- Citizen.Wait(50)
- end
-
- Citizen.Wait(0)
- end
- end)
-end
-
-AddEventHandler('onResourceStop', function(resourceName)
- if GetCurrentResourceName() ~= resourceName then return end
-
- deleteRopeAndNozzleProp()
-end)
-
-function deleteRopeAndNozzleProp()
- if DoesRopeExist(fuelRope) then
- RopeUnloadTextures()
- DeleteRope(fuelRope)
- end
- if DoesEntityExist(fuelNozzle) then
- DeleteEntity(fuelNozzle)
- end
-end
-
-function vehicleCapBoneList()
- return { "petrolcap", "petroltank", "petroltank_l", "petroltank_r", "wheel_lr", "wheel_lf", "engine", "chassis_dummy" }
-end
-
--- Do not change this, use the Config.CustomVehicleParameters in config.lua
-Config.HiddenCustomVehicleParameters = {
- -- Cars
- ["asbo"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.21, up = 0.50} },
- ["blista"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.21, up = 0.50} },
- ["brioso"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.10, up = 0.60} },
- ["club"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.13, up = 0.50} },
- ["kanjo"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.17, up = 0.50} },
- ["issi2"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.15, up = 0.50} },
- ["issi3"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.54} },
- ["issi4"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
- ["issi5"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
- ["issi6"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
- ["panto"] = { distance = 1.2, nozzleOffset = { forward = -0.10, right = -0.15, up = 0.65} },
- ["prairie"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.20, up = 0.45} },
- ["rhapsody"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.20, up = 0.45} },
- ["brioso2"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.13, up = 0.40} },
- ["weevil"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.03, up = 0.63} },
- ["issi7"] = { distance = 1.2, nozzleOffset = { forward = -0.03, right = -0.12, up = 0.57} },
- ["blista2"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.23, up = 0.50} },
- ["blista3"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.23, up = 0.50} },
- ["brioso3"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.06, up = 0.40} },
- ["boor"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.18, up = 0.50} },
- ["asea"] = { distance = 1.2, nozzleOffset = { forward = -0.28, right = -0.21, up = 0.50} },
- ["asterope"] = { distance = 1.2, nozzleOffset = { forward = -0.28, right = -0.16, up = 0.50} },
- ["cog55"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.21, up = 0.45} },
- ["cognoscenti"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.21, up = 0.45} },
- ["emperor"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.22, up = 0.40} },
- ["fugitive"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.40} },
- ["glendale"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.40} },
- ["glendale2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.30} },
- ["ingot"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.45} },
- ["intruder"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.40} },
- ["premier"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.16, up = 0.52} },
- ["primo"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.18, up = 0.40} },
- ["primo2"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.20, up = 0.35} },
- ["regina"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.24, up = 0.40} },
- ["stafford"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.17, up = 0.50} },
- ["stanier"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.40} },
- ["stratum"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.35} },
- ["stretch"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.35} },
- ["superd"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.40} },
- ["tailgater"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.45} },
- ["warrener"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.45} },
- ["washington"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.22, up = 0.45} },
- ["tailgater2"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.14, up = 0.45} },
- ["cinquemila"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.21, up = 0.55} },
- ["astron"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.22, up = 0.55} },
- ["baller7"] = { distance = 1.2, nozzleOffset = { forward = -0.62, right = -0.16, up = 0.60} },
- ["comet7"] = { distance = 1.2, nozzleOffset = { forward = -0.37, right = -0.19, up = 0.45} },
- ["deity"] = { distance = 1.2, nozzleOffset = { forward = -0.37, right = -0.21, up = 0.50} },
- ["jubilee"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.60} },
- ["oracle"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.40} },
- ["schafter2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.45} },
- ["warrener2"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.20, up = 0.40} },
- ["rhinehart"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.15, up = 0.50} },
- ["eudora"] = { distance = 1.2, nozzleOffset = { forward = 0.29, right = -0.38, up = 0.22} },
-
- ["rebla"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.60} },
- ["baller"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.23, up = 0.60} },
- ["baller2"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
- ["baller3"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
- ["baller4"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
- ["baller5"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
- ["baller6"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
- ["bjxl"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.60} },
- ["cavalcade"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.65} },
- ["cavalcade2"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.65} },
- ["contender"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.17, up = 0.50} },
- ["dubsta"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.17, up = 0.70} },
- ["dubsta2"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.17, up = 0.70} },
- ["fq2"] = { distance = 1.2, nozzleOffset = { forward = -0.32, right = -0.23, up = 0.53} },
- ["granger"] = { distance = 1.2, nozzleOffset = { forward = 0.65, right = -0.27, up = 0.60} },
- ["granger2"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.26, up = 0.60} },
- ["gresley"] = { distance = 1.2, nozzleOffset = { forward = 0.05, right = -0.17, up = 0.66} },
- ["habanero"] = { distance = 1.2, nozzleOffset = { forward = -0.47, right = -0.17, up = 0.50} },
- ["huntley"] = { distance = 1.2, nozzleOffset = { forward = 0.07, right = -0.24, up = 0.65} },
- ["landstalker"] = { distance = 1.2, nozzleOffset = { forward = 0.40, right = -0.23, up = 0.60} },
- ["landstalker2"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.24, up = 0.60} },
- ["novak"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.21, up = 0.60} },
- ["patriot"] = { distance = 1.2, nozzleOffset = { forward = 0.2, right = -0.22, up = 0.75} },
- ["patriot2"] = { distance = 1.2, nozzleOffset = { forward = 0.2, right = -0.22, up = 0.75} },
- ["patriot3"] = { distance = 1.2, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.65} },
- ["radi"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.17, up = 0.60} },
- ["rocoto"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.60} },
- ["seminole"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.65} },
- ["seminole2"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.55} },
- ["serrano"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.60} },
- ["toros"] = { distance = 1.2, nozzleOffset = { forward = -0.26, right = -0.26, up = 0.68} },
- ["xls"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.65} },
-
- ["cogcabrio"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
- ["exemplar"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.19, up = 0.45} },
- ["f620"] = { distance = 1.2, nozzleOffset = { forward = -0.29, right = -0.25, up = 0.40} },
- ["felon"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.40} },
- ["felon2"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.40} },
- ["jackal"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
- ["oracle2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
- ["sentinel"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
- ["sentinel2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
- ["windsor"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
- ["windsor2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
- ["zion"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.50} },
- ["zion2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.50} },
- ["previon"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.50} },
- ["champion"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.40} },
- ["futo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.40} },
- ["sentinel3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.30} },
- ["kanjosj"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.45} },
- ["postlude"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.15, up = 0.45} },
- ["tahoma"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
- ["broadway"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
-
- ["blade"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.31, up = 0.40} },
- ["buccaneer"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.40} },
- ["chino"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.35} },
- ["chino2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.25} },
- ["clique"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.25} },
- ["coquette3"] = { distance = 1.2, nozzleOffset = { forward = 0.43, right = -0.31, up = 0.25} },
- ["deviant"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["dominator"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["dominator2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["dominator3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.40} },
- ["dominator4"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.40} },
- ["dominator7"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
- ["dominator8"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.40} },
- ["dukes"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.31, up = 0.40} },
- ["dukes2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.31, up = 0.40} },
- ["dukes3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.40} },
- ["faction"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.40} },
- ["faction2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.30} },
- ["faction3"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.70} },
- ["ellie"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.05, up = 0.67} },
- ["gauntlet"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.40} },
- ["gauntlet2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.40} },
- ["gauntlet3"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.50} },
- ["gauntlet4"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.18, up = 0.45} },
- ["gauntlet5"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.50} },
- ["hermes"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.31, up = 0.20} },
- ["hotknife"] = { distance = 1.2, nozzleOffset = { forward = 0.40, right = -0.00, up = 0.30} },
- ["hustler"] = { distance = 1.2, nozzleOffset = { forward = -0.62, right = 0.05, up = 0.20} },
- ["impaler"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.27, up = 0.35} },
- ["impaler2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.24, up = 0.35} },
- ["impaler3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.45} },
- ["impaler4"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
- ["imperator"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
- ["imperator2"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
- ["imperator3"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
- ["lurcher"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.30, up = 0.35} },
- ["nightshade"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.07, up = 0.35} },
- ["phoenix"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.35} },
- ["picador"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.23, up = 0.45} },
- ["ratloader2"] = { distance = 1.2, nozzleOffset = { forward = 1.05, right = -0.07, up = 0.35} },
- ["ruiner"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
- ["ruiner2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.35} },
- ["sabregt"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.35} },
- ["sabregt2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.30} },
- ["slamvan"] = { distance = 1.2, nozzleOffset = { forward = 0.90, right = 0.03, up = 0.25} },
- ["slamvan2"] = { distance = 1.2, nozzleOffset = { forward = 0.90, right = -0.18, up = 0.30} },
- ["slamvan3"] = { distance = 1.2, nozzleOffset = { forward = 0.85, right = -0.03, up = 0.10} },
- ["stalion"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
- ["stalion2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
- ["tampa"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.35} },
- ["tulip"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
- ["vamos"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.39} },
- ["vigero"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.22, up = 0.39} },
- ["virgo"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.22, up = 0.39} },
- ["virgo2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.30} },
- ["virgo3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.25, up = 0.30} },
- ["voodoo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.29, up = 0.42} },
- ["yosemite"] = { distance = 1.2, nozzleOffset = { forward = 1.20, right = -0.29, up = 0.25} },
- ["yosemite2"] = { distance = 1.2, nozzleOffset = { forward = 1.22, right = -0.13, up = 0.35} },
- ["buffalo4"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.22, up = 0.50} },
- ["manana"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.30} },
- ["manana2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.30} },
- ["tampa2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.10, up = 0.30} },
- ["ruiner4"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.19, up = 0.35} },
- ["vigero2"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
- ["weevil2"] = { distance = 1.2, nozzleOffset = { forward = 1.90, right = 0.15, up = 0.25} },
- ["buffalo5"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
- ["tulip2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.24, up = 0.35} },
- ["clique2"] = { distance = 1.2, nozzleOffset = { forward = 0.05, right = -0.26, up = 0.60} },
- ["brigham"] = { distance = 1.2, nozzleOffset = { forward = 0.15, right = -0.30, up = 0.40} },
- ["greenwood"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.21, up = 0.50} },
-
- ["ardent"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.35} },
- ["btype"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.05, up = 0.78} },
- ["btype2"] = { distance = 1.2, nozzleOffset = { forward = 0.36, right = 0.07, up = 0.55} },
- ["btype3"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.05, up = 0.78} },
- ["casco"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.30} },
- ["deluxo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.13, up = 0.40} },
- ["dynasty"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.40} },
- ["fagaloa"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.35} },
- ["feltzer3"] = { distance = 1.2, nozzleOffset = { forward = -0.31, right = -0.13, up = 0.55} },
- ["gt500"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.25} },
- ["infernus2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.27, up = 0.35} },
- ["jb700"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.35} },
- ["jb7002"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.35} },
- ["mamba"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.13, up = 0.50} },
- ["michelli"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.18, up = 0.30} },
- ["monroe"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.30} },
- ["nebula"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
- ["peyote"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.26, up = 0.30} },
- ["peyote3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.26, up = 0.30} },
- ["pigalle"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
- ["rapidgt3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
- ["retinue"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
- ["retinue2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
- ["savestra"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.15, up = 0.40} },
- ["stinger"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.13, up = 0.65} },
- ["stingergt"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.30} },
- ["stromberg"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.23, up = 0.35} },
- ["swinger"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
- ["torero"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.21, up = 0.35} },
- ["tornado"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
- ["tornado2"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
- ["tornado5"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
- ["turismo2"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.23, up = 0.40} },
- ["viseris"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.18, up = 0.40} },
- ["z190"] = { distance = 1.2, nozzleOffset = { forward = -0.68, right = -0.10, up = 0.47} },
- ["ztype"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.23, up = 0.30} },
- ["zion3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.30} },
- ["cheburek"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.30} },
- ["toreador"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.22, up = 0.35} },
- ["peyote2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.30} },
- ["coquette2"] = { distance = 1.2, nozzleOffset = { forward = 0.43, right = -0.24, up = 0.25} },
-
- ["alpha"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.40} },
- ["banshee"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.09, up = 0.40} },
- ["bestiagts"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.45} },
- ["buffalo"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
- ["buffalo2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
- ["carbonizzare"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.27, up = 0.50} },
- ["comet2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
- ["comet3"] = { distance = 1.3, nozzleOffset = { forward = -0.52, right = -0.07, up = 0.20} },
- ["comet4"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.35} },
- ["comet5"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
- ["coquette"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.25} },
- ["coquette4"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.25} },
- ["drafter"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.45} },
- ["elegy"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.28, up = 0.30} },
- ["elegy2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.50} },
- ["feltzer2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.15, up = 0.45} },
- ["flashgt"] = { distance = 1.3, nozzleOffset = { forward = -0.31, right = -0.26, up = 0.50} },
- ["furoregt"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.50} },
- ["gb200"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.20, up = 0.40} },
- ["komoda"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["italigto"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.27, up = 0.40} },
- ["jugular"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.16, up = 0.55} },
- ["jester"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.23, up = 0.35} },
- ["jester2"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.23, up = 0.35} },
- ["jester3"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.16, up = 0.40} },
- ["kuruma"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.40} },
- ["kuruma2"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.40} },
- ["locust"] = { distance = 1.3, nozzleOffset = { forward = 0.44, right = 0.00, up = 0.61} },
- ["lynx"] = { distance = 1.3, nozzleOffset = { forward = 0.43, right = -0.24, up = 0.40} },
- ["massacro"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.42} },
- ["massacro2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.42} },
- ["neo"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.23, up = 0.42} },
- ["ninef"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
- ["ninef2"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
- ["omnis"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.31} },
- ["paragon"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.25, up = 0.40} },
- ["pariah"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.19, up = 0.45} },
- ["penumbra"] = { distance = 1.3, nozzleOffset = { forward = -0.25, right = -0.19, up = 0.50} },
- ["penumbra2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.40} },
- ["rapidgt"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
- ["rapidgt2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
- ["raptor"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.40, up = 0.25} },
- ["revolter"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.17, up = 0.45} },
- ["ruston"] = { distance = 1.3, nozzleOffset = { forward = 0.53, right = -0.00, up = 0.53} },
- ["schafter3"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
- ["schafter4"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
- ["schlagen"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
- ["seven70"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.23, up = 0.30} },
- ["specter"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.23, up = 0.30} },
- ["streiter"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.08, up = 0.50} },
- ["sugoi"] = { distance = 1.3, nozzleOffset = { forward = -0.25, right = -0.15, up = 0.50} },
- ["sultan"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["sultan2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["surano"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.26, up = 0.40} },
- ["tropos"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.08, up = 0.40} },
- ["verlierer2"] = { distance = 1.3, nozzleOffset = { forward = 1.60, right = -0.19, up = 0.30} },
- ["vstr"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.55} },
- ["zr350"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.35} },
- ["calico"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.16, up = 0.45} },
- ["futo2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.35} },
- ["euros"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.55} },
- ["remus"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.16, up = 0.45} },
- ["comet6"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.35} },
- ["growler"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.23, up = 0.45} },
- ["vectre"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.17, up = 0.45} },
- ["cypher"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.21, up = 0.45} },
- ["sultan3"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
- ["rt3000"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.45} },
- ["sultanrs"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.13, up = 0.40} },
- ["visione"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.10, up = 0.40} },
- ["cheetah2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.35} },
- ["stingertt"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.35} },
- ["sentinel4"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
- ["sm722"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
- ["tenf"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.23, up = 0.43} },
- ["tenf2"] = { distance = 1.3, nozzleOffset = { forward = 0.43, right = -0.15, up = 0.43} },
- ["everon2"] = { distance = 1.3, nozzleOffset = { forward = -1.03, right = -0.24, up = 0.50} },
- ["issi8"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.21, up = 0.55} },
- ["corsita"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.24, up = 0.30} },
- ["gauntlet6"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.21, up = 0.31} },
- ["coureur"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.22, up = 0.45} },
- ["r300"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.26, up = 0.40} },
- ["panthere"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.14, up = 0.40} },
-
- ["adder"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.19, up = 0.50} },
- ["autarch"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.30} },
- ["banshee2"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.09, up = 0.40} },
- ["bullet"] = { distance = 1.3, nozzleOffset = { forward = -0.00, right = -0.30, up = 0.05} },
- ["cheetah"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.31, up = 0.35} },
- ["entity2"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.35} },
- ["entityxf"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.31, up = 0.35} },
- ["emerus"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.35} },
- ["fmj"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.30} },
- ["furia"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.26, up = 0.35} },
- ["gp1"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.30} },
- ["infernus"] = { distance = 1.3, nozzleOffset = { forward = 0.91, right = -0.14, up = 0.65} },
- ["italigtb"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.20, up = 0.35} },
- ["italigtb2"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.20, up = 0.40} },
- ["krieger"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.21, up = 0.25} },
- ["le7b"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.35, up = 0.25} },
- ["nero"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.25} },
- ["nero2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.25} },
- ["osiris"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.25} },
- ["penetrator"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.25, up = 0.25} },
- ["pfister811"] = { distance = 1.3, nozzleOffset = { forward = 0.75, right = -0.28, up = 0.35} },
- ["prototipo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.35} },
- ["reaper"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.15, up = 0.35} },
- ["s80"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.31, up = 0.30} },
- ["sc1"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.25, up = 0.30} },
- ["sheava"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.17, up = 0.35} },
- ["t20"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.27, up = 0.30} },
- ["taipan"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.25, up = 0.30} },
- ["tempesta"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.10, up = 0.60} },
- ["thrax"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.22, up = 0.30} },
- ["tigon"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.30} },
- ["turismor"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.30} },
- ["tyrant"] = { distance = 1.3, nozzleOffset = { forward = 0.30, right = -0.29, up = 0.50} },
- ["tyrus"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.26, up = 0.30} },
- ["vacca"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.32, up = 0.35} },
- ["vagner"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.29, up = 0.35} },
- ["xa21"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.35} },
- ["zentorno"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.29, up = 0.35} },
- ["zorrusso"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.35} },
- ["ignus"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.32, up = 0.35} },
- ["zeno"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
- ["deveste"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.21, up = 0.25} },
- ["lm87"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.34, up = 0.25} },
- ["torero2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.35} },
- ["entity3"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.25} },
- ["virtue"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.19, up = 0.35} },
-
- ["bfinjection"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = 0.02, up = 0.35} },
- ["bifta"] = { distance = 1.3, nozzleOffset = { forward = 0.03, right = -0.65, up = 0.10} },
-
- -- offroad
- ["blazer"] = { distance = 1.3, nozzleOffset = { forward = -0.08, right = -0.29, up = 0.20} },
- ["blazer2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.25, up = 0.25} },
- ["blazer3"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.25, up = 0.15} },
- ["blazer4"] = { distance = 1.3, nozzleOffset = { forward = -0.00, right = -0.22, up = 0.12} },
- ["blazer5"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.55, up = 0.25} },
- ["brawler"] = { distance = 1.3, nozzleOffset = { forward = -0.16, right = -0.13, up = 0.90} },
- ["caracara"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.80} },
- ["caracara2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.80} },
- ["dubsta3"] = { distance = 1.3, nozzleOffset = { forward = -0.75, right = -0.97, up = 0.40} },
- ["dune"] = { distance = 1.3, nozzleOffset = { forward = 0.05, right = -0.65, up = 0.05} },
- ["everon"] = { distance = 1.3, nozzleOffset = { forward = -0.80, right = -0.04, up = 0.80} },
- ["freecrawler"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.20, up = 1.00} },
- ["hellion"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.17, up = 0.40} },
- ["kalahari"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
- ["kamacho"] = { distance = 1.3, nozzleOffset = { forward = 1.05, right = -0.02, up = 0.60} },
- ["mesa3"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = 0.02, up = 0.85} },
- ["outlaw"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.13, up = 0.70} },
- ["rancherxl"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.50} },
- ["rebel2"] = { distance = 1.3, nozzleOffset = { forward = 1.10, right = -0.09, up = 0.55} },
- ["riata"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.02, up = 0.80} },
- ["sandking"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.17, up = 0.70} },
- ["sandking2"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.17, up = 0.70} },
- ["trophytruck"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.10, up = 0.70} },
- ["trophytruck2"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.10, up = 0.70} },
- ["vagrant"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = 0.15, up = 0.25} },
- ["verus"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.30, up = 0.08} },
- ["winky"] = { distance = 1.3, nozzleOffset = { forward = -1.00, right = -0.19, up = 0.50} },
- ["yosemite3"] = { distance = 1.3, nozzleOffset = { forward = 0.83, right = -0.19, up = 0.50} },
- ["mesa"] = { distance = 1.3, nozzleOffset = { forward = 0.30, right = -0.11, up = 0.66} },
- ["ratel"] = { distance = 1.3, nozzleOffset = { forward = 0.61, right = 0.16, up = 1.11} },
- ["l35"] = { distance = 1.3, nozzleOffset = { forward = 0.80, right = -0.17, up = 0.55} },
- ["monstrociti"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.45} },
- ["draugur"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.16, up = 0.80} },
-
- -- truck
- ["guardian"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.16, up = 0.40} },
- ["mixer2"] = { distance = 1.3, nozzleOffset = { forward = 0.0, right = 0.11, up = -0.06} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["tiptruck2"] = { distance = 3.5, nozzleOffset = { forward = 2.00, right = -2.25, up = -0.24} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["tiptruck"] = { distance = 1.3, nozzleOffset = { forward = 0.01, right = -0.19, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["rubble"] = { distance = 1.3, nozzleOffset = { forward = 0.01, right = -0.19, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["mixer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.23, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["flatbed"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.23, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dump"] = { distance = 1.3, nozzleOffset = { forward = 0.27, right = -0.57, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["bulldozer"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.25, up = 0.80} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["handler"] = { distance = 1.3, nozzleOffset = { forward = 0.88, right = -0.52, up = 0.88} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cutter"] = { distance = 1.3, nozzleOffset = { forward = 0.95, right = -0.42, up = 0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
-
- -- utillity
- ["slamtruck"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.26} },
- ["utillitruck"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -1.25, up = 0.50} },
- ["utillitruck2"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -1.25, up = 0.50} },
- ["utillitruck3"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = -0.30, up = 0.50} },
- ["tractor"] = { distance = 2.0, nozzleOffset = { forward = 1.50, right = 0.27, up = 0.30} },
- ["tractor2"] = { distance = 2.0, nozzleOffset = { forward = 1.60, right = 0.05, up = 0.20} },
- ["tractor3"] = { distance = 2.0, nozzleOffset = { forward = 1.60, right = 0.05, up = 0.20} },
- ["towtruck"] = { distance = 2.0, nozzleOffset = { forward = -0.45, right = -0.30, up = 0.10} },
- ["towtruck2"] = { distance = 2.0, nozzleOffset = { forward = 0.85, right = 0.05, up = 0.50} },
- ["scrap"] = { distance = 2.0, nozzleOffset = { forward = -0.52, right = -0.05, up = -0.05} },
- ["sadler"] = { distance = 1.3, nozzleOffset = { forward = 1.14, right = -0.22, up = 0.70} },
- ["ripley"] = { distance = 2.0, nozzleOffset = { forward = -0.95, right = -0.48, up = 0.40} },
- ["mower"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = 0.10, up = 0.63} },
- ["forklift"] = { distance = 1.3, nozzleOffset = { forward = 0.05, right = -0.27, up = -0.40} },
- ["docktug"] = { distance = 2.5, nozzleOffset = { forward = 0.0, right = -0.25, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
-
- -- van
- ["bison"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.26} },
- ["bobcatxl"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.35} },
- ["burrito3"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.25, up = 0.35} },
- ["gburrito2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.22, up = 0.35} },
- ["rumpo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.25, up = 0.35} },
- ["journey"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.34, up = 0.45} },
- ["minivan"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.20, up = 0.45} },
- ["minivan2"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.20, up = 0.45} },
- ["paradise"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.23, up = 0.45} },
- ["rumpo3"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.45} },
- ["speedo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
- ["speedo4"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
- ["surfer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.29, up = 0.45} },
- ["youga3"] = { distance = 1.3, nozzleOffset = { forward = 0.55, right = -0.18, up = 0.45} },
- ["youga"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.23, up = 0.45} },
- ["youga2"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.25, up = 0.40} },
- ["youga4"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.30, up = 0.40} },
- ["moonbeam"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.28, up = 0.40} },
- ["moonbeam2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
- ["boxville"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
- ["boxville2"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
- ["boxville3"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
- ["boxville4"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
- ["boxville5"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
- ["pony"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
- ["pony2"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.26, up = 0.40} },
- ["journey2"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.34, up = 0.45} },
- ["surfer3"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.29, up = 0.45} },
- ["speedo5"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
- ["mule2"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
- ["taco"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
-
-
- -- Lspd, ems ....
- ["riot"] = { distance = 2.5, nozzleOffset = { forward = -0.80, right = -1.30, up = 0.30} },
- ["riot2"] = { distance = 1.3, nozzleOffset = { forward = -0.70, right = -0.09, up = 0.65} },
- ["pbus"] = { distance = 1.3, nozzleOffset = { forward = -0.70, right = -0.30, up = 0.65} },
- ["police"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
- ["police2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.50} },
- ["police3"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
- ["police4"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
- ["sheriff"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
- ["sheriff2"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.60} },
- ["policeold1"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.60} },
- ["policeold2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.40} },
- ["policet"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.26, up = 0.60} },
- ["policeb"] = { distance = 1.3, nozzleOffset = { forward = -0.18, right = -0.18, up = 0.10}, nozzleRotation = { x = 0, y = 0, z = 60} },
- ["polmav"] = { distance = 3.0, nozzleOffset = { forward = 0.12, right = -0.60, up = -0.45}, nozzleRotation = { x = 0, y = 0, z = 20} },
- ["ambulance"] = { distance = 1.3, nozzleOffset = { forward = 2.95, right = -0.08, up = 0.50} },
- ["firetruk"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.32, up = 0.70} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["lguard"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
- ["pranger"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
- ["fbi"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.40} },
- ["fbi2"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
- ["predator"] = { distance = 3.5, nozzleOffset = { forward = 1.80, right = 1.58, up = 0.17}, nozzleRotation = { x = 0, y = 0, z = 180} },
-
- -- Military
- ["apc"] = { distance = 2.5, nozzleOffset = { forward = -0.80, right = -1.00, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["barracks"] = { distance = 3.5, nozzleOffset = { forward = 0.00, right = -0.25, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["barracks2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.28, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["barracks3"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.16, up = -0.03} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["chernobog"] = { distance = 2.5, nozzleOffset = { forward = 3.70, right = -0.20, up = 0.22} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["crusader"] = { distance = 1.5, nozzleOffset = { forward = 0.25, right = -0.11, up = 0.65} },
- ["halftrack"] = { distance = 1.5, nozzleOffset = { forward = -0.60, right = -0.30, up = 0.90} },
- ["khanjali"] = { distance = 1.5, nozzleOffset = { forward = -0.55, right = -0.80, up = 0.95} },
- ["rhino"] = { distance = 1.5, nozzleOffset = { forward = -0.05, right = -0.52, up = 1.00} },
- ["scarab"] = { distance = 1.5, nozzleOffset = { forward = 0.60, right = 0.15, up = 1.08} },
- ["terbyte"] = { distance = 1.5, nozzleOffset = { forward = -0.700, right = -0.47, up = 0.65} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["vetir"] = { distance = 3.0, nozzleOffset = { forward = 1.25, right = 1.95, up = 0.40} , nozzleRotation = { x = 0, y = 0, z = 180} },
-
- ["thruster"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = 0.40, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["minitank"] = { distance = 1.5, nozzleOffset = { forward = 0.05, right = -0.05, up = 0.49} },
-
- -- Electric cars
- ["voltic"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.45} },
- ["voltic2"] = { distance = 1.3, nozzleOffset = { forward = -0.12, right = 0.12, up = 0.57} },
- ["caddy"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.53} },
- ["caddy2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.35} },
- ["caddy3"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.35} },
- ["surge"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.45} },
- ["iwagen"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.50} },
- ["raiden"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.13, up = 0.50} },
- ["airtug"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.18, up = 0.47} },
- ["neon"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.50} },
- ["omnisegt"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.40} },
- ["cyclone"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.45} },
- ["tezeract"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.48} },
- ["imorgon"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.48} },
- ["dilettante"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.48} },
- ["dilettante2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.48} },
- ["khamelion"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.20, up = 0.48} },
-
- ["rcbandito"] = { distance = 1.3, nozzleOffset = { forward = -0.12, right = 0.12, up = 0.22} },
-
-
- -- Motorcycles
- ["akuma"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.20, up = 0.20} },
- ["avarus"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["bagger"] = { distance = 1.1, nozzleOffset = { forward = -0.26, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["bati"] = { distance = 1.1, nozzleOffset = { forward = -0.15, right = -0.25, up = 0.20} },
- ["bati2"] = { distance = 1.1, nozzleOffset = { forward = -0.15, right = -0.24, up = 0.20} },
- ["bf400"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.24, up = 0.29} },
- ["carbonrs"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.22, up = 0.20} },
- ["chimera"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.00, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["cliffhanger"] = { distance = 1.1, nozzleOffset = { forward = -0.33, right = 0.05, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["daemon"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["daemon2"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["defiler"] = { distance = 1.1, nozzleOffset = { forward = 0.09, right = -0.23, up = 0.20} },
- ["deathbike"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["deathbike2"] = { distance = 1.1, nozzleOffset = { forward = -0.25, right = 0.03, up = 0.07} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["deathbike3"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["diablous"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.06, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["diablous2"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.03, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["double"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.22, up = 0.20} },
- ["enduro"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.17, up = 0.25} },
- ["esskey"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.20, up = 0.20} },
- ["faggio"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = -0.28, up = 0.30} },
- ["faggio2"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = 0.25, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["faggio3"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = 0.25, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["fcr"] = { distance = 1.1, nozzleOffset = { forward = -0.03, right = -0.21, up = 0.10} },
- ["gargoyle"] = { distance = 1.1, nozzleOffset = { forward = -0.26, right = 0.03, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["hakuchou"] = { distance = 1.1, nozzleOffset = { forward = 0.05, right = -0.17, up = 0.10} },
- ["hakuchou2"] = { distance = 1.1, nozzleOffset = { forward = 0.00, right = -0.19, up = 0.10} },
- ["hexer"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.04, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["innovation"] = { distance = 1.1, nozzleOffset = { forward = -0.23, right = 0.02, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["lectro"] = { distance = 1.1, nozzleOffset = { forward = -0.12, right = -0.20, up = 0.20} },
- ["manchez"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.20, up = 0.10} },
- ["nemesis"] = { distance = 1.1, nozzleOffset = { forward = -0.03, right = -0.17, up = 0.10} },
- ["nightblade"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.05, up = 0.14} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["oppressor"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.05, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["pcj"] = { distance = 1.1, nozzleOffset = { forward = 0.04, right = -0.20, up = 0.20} },
- ["ratbike"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["ruffian"] = { distance = 1.1, nozzleOffset = { forward = 0.04, right = -0.19, up = 0.20} },
- ["sanchez"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.22, up = 0.25} },
- ["sanchez2"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.22, up = 0.25} },
- ["sanctus"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.08} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["shotaro"] = { distance = 1.1, nozzleOffset = { forward = 0.06, right = -0.25, up = 0.20} },
- ["sovereign"] = { distance = 1.1, nozzleOffset = { forward = -0.07, right = -0.23, up = 0.15} },
- ["stryder"] = { distance = 1.1, nozzleOffset = { forward = 0.06, right = -0.20, up = 0.15} },
- ["thrust"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.25, up = 0.15} },
- ["vader"] = { distance = 1.1, nozzleOffset = { forward = 0.10, right = -0.25, up = 0.20} },
- ["vindicator"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.25, up = 0.15} },
- ["vortex"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.20, up = 0.12} },
- ["wolfsbane"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["zombiea"] = { distance = 1.1, nozzleOffset = { forward = -0.14, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["zombieb"] = { distance = 1.1, nozzleOffset = { forward = -0.21, right = 0.03, up = 0.15} , nozzleRotation = { x = 0, y = 0, z = 90} },
- ["manchez2"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.10} },
- ["shinobi"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.20} },
- ["reever"] = { distance = 1.1, nozzleOffset = { forward = 0.09, right = -0.20, up = 0.10} },
- ["manchez3"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.10} },
-
- -- truck 2
- ["pounder2"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.12, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["mule4"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
- ["phantom3"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["hauler2"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = 0.02} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["phantom2"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["mule5"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
- ["stockade"] = { distance = 3.0, nozzleOffset = { forward = -0.50, right = -1.36, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["pounder"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.12, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["phantom"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["packer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["mule"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
- ["hauler"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = -0.02} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["biff"] = { distance = 1.3, nozzleOffset = { forward = 0.0, right = 0.11, up = -0.06} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["benson"] = { distance = 1.3, nozzleOffset = { forward = 0.32, right = 0.40, up = 0.21} , nozzleRotation = { x = 0, y = 0, z = 180} },
-
- --helicopters
- ["conada2"] = { distance = 3.5, nozzleOffset = { forward = -0.10, right = -0.90, up = 0.20}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["akula"] = { distance = 3.5, nozzleOffset = { forward = -1.50, right = -0.65, up = -0.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["annihilator2"] = { distance = 3.5, nozzleOffset = { forward = -1.10, right = -1.25, up = -1.70}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["annihilator"] = { distance = 3.5, nozzleOffset = { forward = -1.20, right = -1.05, up = -1.70}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["havok"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.49, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["hunter"] = { distance = 3.5, nozzleOffset = { forward = -1.50, right = -0.69, up = -0.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["seasparrow"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["seasparrow2"] = { distance = 3.2, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["supervolito"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.87, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["supervolito2"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.87, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["swift"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.90, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["swift2"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.90, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["valkyrie"] = { distance = 2.5, nozzleOffset = { forward = 1.60, right = -1.21, up = -1.80}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["valkyrie2"] = { distance = 2.5, nozzleOffset = { forward = 1.60, right = -1.21, up = -1.80}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["volatus"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.86, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["savage"] = { distance = 3.5, nozzleOffset = { forward = -0.10, right = -1.09, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["buzzard2"] = { distance = 2.2, nozzleOffset = { forward = -1.10, right = -0.76, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 10} },
- ["buzzard"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.76, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 10} },
- ["cargobob"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cargobob2"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cargobob3"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cargobob4"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["conada"] = { distance = 2.0, nozzleOffset = { forward = -0.09, right = -0.90, up = 0.20}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["frogger"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = -0.92, up = -0.90}, nozzleRotation = { x = 0, y = 0, z = 20} },
- ["frogger2"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = -0.92, up = -0.90}, nozzleRotation = { x = 0, y = 0, z = 20} },
- ["seasparrow3"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
- ["skylift"] = { distance = 4.0, nozzleOffset = { forward = 4.95, right = 0.00, up = -3.50}, nozzleRotation = { x = 0, y = 0, z = 90} },
- ["maverick"] = { distance = 3.5, nozzleOffset = { forward = 0.00, right = -0.90, up = -1.50}, nozzleRotation = { x = 0, y = 0, z = 20} },
-
- -- Boats
- ["toro"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.75, up = 0.48 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["toro2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.75, up = 0.48 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["patrolboat"] = { distance = 1.0, nozzleOffset = { forward = -0.30, right = 0.25, up = 0.20 } , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["longfin"] = { distance = 1.5, nozzleOffset = { forward = 0.90 , right = -1.40, up = 0.68} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["speeder"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.65 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["speeder2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.65 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["tropic"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = -1.15, up = 0.71} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["tropic2"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = -1.15, up = 0.71} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["suntrap"] = { distance = 2.0, nozzleOffset = { forward = 0.55, right = -0.95, up = 0.93} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["squalo"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.57 } , nozzleRotation = { x = -60, y = 0, z = 90} },
- ["marquis"] = { distance = 1.5, nozzleOffset = { forward = 0.50, right = -1.35, up = 1.36 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["jetmax"] = { distance = 2.0, nozzleOffset = { forward = 0.50, right = -0.90, up = 0.54 } , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["dinghy"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dinghy2"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dinghy3"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dinghy4"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dinghy5"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
-
- -- Jet
- ["seashark"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
- ["seashark3"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
- ["seashark2"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
-
- -- Submarine
- ["avisa"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = -1.30, up = 0.14 } , nozzleRotation = { x = -85, y = 0, z = 90} },
- ["submersible2"] = { distance = 2.5, nozzleOffset = { forward = -0.40, right = -0.70, up = 1.20 } , nozzleRotation = { x = -90, y = 0, z = 0} },
- ["submersible"] = { distance = 2.5, nozzleOffset = { forward = -0.60, right = -0.85, up = 1.20 } , nozzleRotation = { x = -90, y = 0, z = 0} },
-
- -- Big boats
--- ["kosatka"] = { distance = 6.0, nozzleOffset = { forward = 0.0, right = -0.15, up = 1.0 } }, ----- BIG SUBMARINE
- ["tug"] = { distance = 2.5, nozzleOffset = { forward = 0.0, right = 0.79, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 180} },
-
- -- Plane
- ["streamer216"] = { distance = 1.5, nozzleOffset = { forward = -0.40, right = 1.02, up = 1.10 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["raiju"] = { distance = 3.0, nozzleOffset = { forward = 1.0, right = -0.85, up = -0.25 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["alkonost"] = { distance = 11.0, nozzleOffset = { forward = -2.60, right = -5.30, up = 0.90 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["strikeforce"] = { distance = 3.0, nozzleOffset = { forward = 3.0, right = 1.37, up = 1.60 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["blimp3"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["avenger"] = { distance = 2.0, nozzleOffset = { forward = -0.60, right = -0.73, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["avenger2"] = { distance = 2.0, nozzleOffset = { forward = -0.60, right = -0.73, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["volatol"] = { distance = 2.0, nozzleOffset = { forward = 0.80, right = 0.46, up = 1.85} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["nokota"] = { distance = 2.5, nozzleOffset = { forward = -1.50, right = 1.60, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["seabreeze"] = { distance = 2.5, nozzleOffset = { forward = -0.20, right = -0.10, up = -1.70} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["pyro"] = { distance = 3.0, nozzleOffset = { forward = 2.10, right = 1.56, up = 0.90} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["mogul"] = { distance = 2.0, nozzleOffset = { forward = 0.30, right = -0.68, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["howard"] = { distance = 2.5, nozzleOffset = { forward = 1.80, right = 1.25, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["bombushka"] = { distance = 2.5, nozzleOffset = { forward = 0.50, right = -0.71, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["molotok"] = { distance = 3.5, nozzleOffset = { forward = 2.00, right = -0.85, up = 0.55} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["microlight"] = { distance = 3.5, nozzleOffset = { forward = -0.02, right = 0.48, up = 0.30} , nozzleRotation = { x = 0, y = 0, z = 45} },
- ["tula"] = { distance = 3.5, nozzleOffset = { forward = 0.70, right = -0.52, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["rogue"] = { distance = 3.5, nozzleOffset = { forward = 0.10, right = -0.15, up = 0.45} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["starling"] = { distance = 3.5, nozzleOffset = { forward = 0.10, right = -0.08, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["alphaz1"] = { distance = 3.5, nozzleOffset = { forward = -1.00, right = -0.03, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["nimbus"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = -0.10, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["luxor2"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = 0.80, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["velum2"] = { distance = 5.0, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["hydra"] = { distance = 2.5, nozzleOffset = { forward = -1.80, right = 1.88, up = 1.35} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["blimp2"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["dodo"] = { distance = 2.0, nozzleOffset = { forward = -0.15, right = -0.13, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["miljet"] = { distance = 6.0, nozzleOffset = { forward = 2.75, right = -0.47, up = -1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["vestra"] = { distance = 2.5, nozzleOffset = { forward = 2.50, right = 1.35, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cargoplane"] = { distance = 2.5, nozzleOffset = { forward = 1.50, right = 0.27, up = 1.60} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["velum"] = { distance = 5.0, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["titan"] = { distance = 2.5, nozzleOffset = { forward = 0.50, right = -0.46, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["shamal"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.10, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["lazer"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.09, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["stunt"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.08, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["luxor"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = 0.80, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["jet"] = { distance = 15.0, nozzleOffset = { forward = 1.20, right = 1.20, up = 2.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["duster"] = { distance = 2.5, nozzleOffset = { forward = -0.20, right = -0.15, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["cuban800"] = { distance = 2.5, nozzleOffset = { forward = 1.00, right = 0.51, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["blimp"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
-
- -- Service
- ["brickade"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = 0.16, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["brickade2"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = 0.16, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
- ["pbus2"] = { distance = 3.0, nozzleOffset = { forward = -2.38, right = -0.30, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["wastelander"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.05, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["rallytruck"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
--- ["metrotrain"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, --- metro
--- ["freight"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, -- train
--- ["cablecar"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, -- cablecar
- ["trash"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.15, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["trash2"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.15, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["tourbus"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.33, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["taxi"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.45} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["rentalbus"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.33, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["coach"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.29, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["bus"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.28, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
- ["airbus"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.28, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
-
- -- Race
- ["openwheel2"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.60, up = 0.30} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["openwheel1"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.60, up = 0.35} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["formula2"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.50, up = 0.29} , nozzleRotation = { x = -75, y = 0, z = 90} },
- ["formula"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.50, up = 0.29} , nozzleRotation = { x = -75, y = 0, z = 90} },
-}
+-- Shared variables
+Utils = Utils or exports['lc_utils']:GetUtils()
+cachedTranslations = {}
+mainUiOpen = false
+
+fuelNozzle = 0
+fuelRope = 0
+currentPump = 0
+JERRY_CAN_HASH = 883325847
+
+-- Fuel chart variables
+isFuelConsumptionChartOpen = false
+isRecording = true
+
+-- Local variables
+local fuelDecor = "_FUEL_LEVEL"
+local currentConsumption = 0.0
+local fuelSynced = false
+local closestVehicleToPump = 0
+local isNuiVariablesLoaded = false
+
+DecorRegister(fuelDecor, 1)
+-- Check if it actually registered
+if DecorIsRegisteredAsType(fuelDecor, 1) then
+ print("[Fuel Script] SUCCESS: fuelDecor was registered successfully!")
+else
+ print("[Fuel Script] ERROR: fuelDecor registration failed!")
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Threads
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+-- Thread to handle the fuel consumption
+function createFuelConsumptionThread()
+ CreateThread(function()
+ local currentVehicle = nil
+ local currentVehicleFuelType = "default" -- default while the callback loads
+ DecorRegister(fuelDecor, 1)
+ while true do
+ Wait(1000)
+ local ped = PlayerPedId()
+ if IsPedInAnyVehicle(ped, false) then
+ local vehicle = GetVehiclePedIsIn(ped, false)
+ if GetPedInVehicleSeat(vehicle, -1) == ped and not IsVehicleBlacklisted(vehicle) then
+ if currentVehicle == nil or currentVehicle ~= vehicle then
+ currentVehicle = vehicle
+ currentVehicleFuelType = getVehicleFuelTypeFromServer(vehicle)
+ fuelSynced = false
+ end
+ HandleFuelConsumption(vehicle, currentVehicleFuelType)
+ end
+ else
+ if isFuelConsumptionChartOpen then
+ closeFuelConsumptionChartUI()
+ end
+ currentVehicleFuelType = "default"
+ currentVehicle = nil
+ fuelSynced = false
+ end
+ end
+ end)
+end
+
+function HandleFuelConsumption(vehicle, fuelType)
+ -- If no decorator exists, set a random fuel %
+ if not DecorExistOn(vehicle, fuelDecor) then
+ SetFuel(vehicle, math.random(200, 800) / 10)
+ elseif not fuelSynced then
+ -- Sync once
+ SetFuel(vehicle, GetFuel(vehicle))
+ fuelSynced = true
+ end
+
+ -- If engine is off, do nothing
+ if not GetIsVehicleEngineRunning(vehicle) then
+ return
+ end
+
+ -- Turns engine off if have no fuel
+ local currentFuelLevel = GetVehicleFuelLevel(vehicle)
+ if currentFuelLevel <= 0.0 then
+ SetVehicleEngineOn(vehicle, false, true, false)
+ return
+ end
+
+ -- Get the vehicle's actual tank size in liters
+ local tankSize = getVehicleTankSize(vehicle)
+
+ -- Base consumption from config and RPM
+ currentConsumption = Config.FuelUsage[Utils.Math.round(GetVehicleCurrentRpm(vehicle), 1)] * (Config.FuelConsumptionPerClass[GetVehicleClass(vehicle)] or 1.0) * (Config.FuelConsumptionPerFuelType[fuelType] or 1.0) / 10
+
+ -- Scale consumption according to tank size.
+ -- A smaller tank will lose percentage faster; a bigger tank slower.
+ local scaledConsumption = currentConsumption * (100 / tankSize)
+
+ -- Subtract from the current fuel %
+ local newFuelLevel = currentFuelLevel - scaledConsumption
+
+ -- Write the new fuel % back
+ SetFuel(vehicle, newFuelLevel)
+
+ -- Store data for chart
+ if Config.FuelConsumptionChart.enabled then
+ storeDataForChart(vehicle, newFuelLevel, currentConsumption)
+ end
+
+ validateDieselFuelMismatch(vehicle, fuelType)
+end
+
+function validateDieselFuelMismatch(vehicle, fuelType)
+ if (fuelType == "diesel" and not IsVehicleDiesel(vehicle)) or (fuelType ~= "diesel" and IsVehicleDiesel(vehicle)) then
+ SetTimeout(5000, function()
+ if IsVehicleDriveable(vehicle, false) then
+ SetVehicleEngineHealth(vehicle, 0.0)
+ SetVehicleUndriveable(vehicle, true)
+ exports['lc_utils']:notify("error", Utils.translate("vehicle_wrong_fuel"))
+ end
+ end)
+ end
+end
+
+function createDebugNozzleOffsetThread()
+ CreateThread(function()
+ while true do
+ local vehicle = GetVehiclePlayerIsLookingAt()
+ if not vehicle or not DoesEntityExist(vehicle) then
+ Wait(2)
+ goto continue -- Skip if no valid vehicle found
+ end
+
+ local hit, hitCoords = GetLookAtHitCoords()
+ if hit and DoesEntityExist(vehicle) then
+ local offset = GetNozzleOffset(vehicle, hitCoords)
+
+ if offset then
+ local vehCoords = GetEntityCoords(vehicle)
+
+ -- Get vehicle's axis vectors
+ local _, rightVector, _ = GetEntityMatrix(vehicle)
+
+ -- Direction from vehicle to hit point
+ local directionToHit = hitCoords - vehCoords
+ directionToHit = directionToHit / #(directionToHit) -- normalize
+
+ -- Dot product with right vector
+ local side = rightVector.x * directionToHit.x + rightVector.y * directionToHit.y + rightVector.z * directionToHit.z
+
+ -- Adjust offset.right
+ if side > 0 then
+ -- hit is on the right side
+ offset.right = offset.right + 0.07
+ else
+ -- hit is on the left side
+ offset.right = offset.right - 0.07
+ end
+
+ -- Final world position of the nozzle point
+ local finalWorldPos = getWorldPosFromOffset(vehicle, offset)
+
+ -- Draw a small marker at the computed position
+ DrawMarker(28, finalWorldPos.x, finalWorldPos.y, finalWorldPos.z + 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.03, 0.03, 0.03, 255, 0, 0, 180, false, true, 2, nil, nil, false)
+
+ if IsControlJustPressed(0,38) then
+ local model = GetEntityModel(vehicle)
+ local modelName = GetDisplayNameFromVehicleModel(model):lower()
+
+ local zRotation = side > 0 and 180 or 0
+
+ local clipboardText = string.format(
+ '["%s"] = { distance = 1.3, nozzleOffset = { forward = %.2f, right = %.2f, up = %.2f }, nozzleRotation = { x = 0, y = 0, z = %d } },',
+ modelName,
+ offset.forward, offset.right, offset.up,
+ zRotation
+ )
+
+ SendNUIMessage({
+ type = "copyToClipboard",
+ text = clipboardText
+ })
+
+ exports['lc_utils']:notify("success", "Copied to clipboard: " .. clipboardText)
+ exports['lc_utils']:notify("warning", "Make sure the vehicle spawn name is correct. You may need to manually fine-tune the offset and rotation.")
+ end
+ end
+ end
+ Wait(2)
+ ::continue::
+ end
+ end)
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- UI
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function clientOpenUI(pump, pumpModel, isElectricPump)
+ currentPump = pump
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+
+ closestVehicleToPump = GetClosestVehicle(playerCoords)
+ local isElectricVehicle = IsVehicleElectric(closestVehicleToPump)
+ if not (isElectricVehicle and isElectricPump) and not (not isElectricVehicle and not isElectricPump) then
+ -- Reset the near vehicle to 0 when it does not match the pump type (only allows electric vehicle in electric chargers and gas vehicles in gas pumps)
+ closestVehicleToPump = 0
+ end
+
+ pumpLocation = nil
+
+ if closestVehicleToPump and #(playerCoords - GetEntityCoords(closestVehicleToPump)) < 5 then
+ -- Load the nearest vehicle fuel and plate (fuel type)
+ local vehicleFuel = GetFuel(closestVehicleToPump)
+ local vehiclePlate = GetVehicleNumberPlateText(closestVehicleToPump)
+ local vehicleTankSize = getVehicleTankSize(closestVehicleToPump)
+ local vehicleDisplayFuelAmount = getVehicleDisplayFuelAmount(vehicleFuel, vehicleTankSize)
+ TriggerServerEvent("lc_fuel:serverOpenUI", isElectricPump, pumpModel, vehicleDisplayFuelAmount, vehicleTankSize, vehiclePlate)
+ else
+ -- Allow the user to open the UI even without vehicles nearby
+ TriggerServerEvent("lc_fuel:serverOpenUI", isElectricPump, pumpModel)
+ end
+end
+
+function loadNuiVariables()
+ if isNuiVariablesLoaded then
+ return
+ end
+
+ -- Load NUI variables
+ SendNUIMessage({
+ utils = { config = Utils.Config, lang = Utils.Lang },
+ resourceName = GetCurrentResourceName()
+ })
+
+ local maxIterations = 100 -- Maximum number of iterations (100 * 100ms = 10 seconds)
+ local iterations = 0
+
+ while not isNuiVariablesLoaded do
+ Wait(100)
+ iterations = iterations + 1
+
+ if iterations >= maxIterations then
+ print("Error: Timeout while loading NUI variables after " .. iterations .. " attempts.")
+ return
+ end
+ end
+end
+
+
+RegisterNetEvent('lc_fuel:clientOpenUI')
+AddEventHandler('lc_fuel:clientOpenUI', function(data)
+ loadNuiVariables()
+ data.currentFuelType = dealWithDefaultFuelType(closestVehicleToPump, data.currentFuelType)
+ SendNUIMessage({
+ openMainUI = true,
+ data = data
+ })
+ mainUiOpen = true
+ TriggerScreenblurFadeIn(1000)
+ FreezeEntityPosition(PlayerPedId(), true)
+ SetNuiFocus(true,true)
+end)
+
+RegisterNUICallback('post', function(body, cb)
+ if cooldown == nil then
+ cooldown = true
+
+ if body.event == "close" then
+ closeUI()
+ elseif body.event == "closeFuelConsumptionChartUI" then
+ closeFuelConsumptionChartUI()
+ elseif body.event == "removeFocusFuelConsumptionChartUI" then
+ SetNuiFocus(false,false)
+ elseif body.event == "startRecordingGraph" then
+ isRecording = true
+ elseif body.event == "stopRecordingGraph" then
+ isRecording = false
+ elseif body.event == "notify" then
+ exports['lc_utils']:notify(body.data.type,body.data.msg)
+ elseif body.event == "changeVehicleFuelType" then
+ changeVehicleFuelType(closestVehicleToPump, body.data.selectedFuelType)
+ else
+ TriggerServerEvent('lc_fuel:'..body.event,body.data)
+ end
+ cb(200)
+
+ SetTimeout(5,function()
+ cooldown = nil
+ end)
+ end
+end)
+
+RegisterNUICallback('setNuiVariablesLoaded', function(body, cb)
+ isNuiVariablesLoaded = true
+ cb(200)
+end)
+
+function closeUI()
+ mainUiOpen = false
+ FreezeEntityPosition(PlayerPedId(), false)
+ TriggerScreenblurFadeOut(1000)
+ SetNuiFocus(false,false)
+ SendNUIMessage({ hideMainUI = true })
+end
+
+RegisterNetEvent('lc_fuel:closeUI')
+AddEventHandler('lc_fuel:closeUI', function()
+ closeUI()
+end)
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Exports
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function GetFuel(vehicle)
+ if not DoesEntityExist(vehicle) then
+ warn(("[GetFuel] Vehicle entity does not exist. Received: %s. This is usually caused by a misconfiguration in the export."):format(tostring(vehicle)))
+ return 0
+ end
+ return DecorGetFloat(vehicle, fuelDecor)
+end
+exports('GetFuel', GetFuel)
+
+function SetFuel(vehicle, fuel)
+ if not DoesEntityExist(vehicle) then
+ warn(("[SetFuel] Vehicle entity does not exist. Received: %s. This is usually caused by a misconfiguration in the export."):format(tostring(vehicle)))
+ return
+ end
+
+ if type(fuel) ~= "number" then
+ warn(("[SetFuel] Invalid fuel value received: %s. Fuel must be a number between 0 and 100."):format(tostring(fuel)))
+ return
+ end
+
+ -- Normalize the fuel values if received negative values or higher than 100
+ fuel = math.max(0.0, math.min(fuel, 100.0))
+
+ SetVehicleFuelLevel(vehicle, fuel + 0.0)
+ DecorSetFloat(vehicle, fuelDecor, GetVehicleFuelLevel(vehicle))
+end
+exports('SetFuel', SetFuel)
+
+-- Just another way to call the exports in case someone does it like this...
+function getFuel(vehicle)
+ return GetFuel(vehicle)
+end
+exports('getFuel', getFuel)
+
+function setFuel(vehicle, fuel)
+ SetFuel(vehicle, fuel)
+end
+exports('setFuel', setFuel)
+
+-- Alias LegacyFuel's exports to point to our lc_fuel functions:
+AddEventHandler('__cfx_export_LegacyFuel_SetFuel', function(setCB)
+ -- Redirect LegacyFuel:SetFuel to use lc_fuel's SetFuel function
+ setCB(SetFuel)
+end)
+
+AddEventHandler('__cfx_export_LegacyFuel_GetFuel', function(setCB)
+ -- Redirect LegacyFuel:GetFuel to use lc_fuel's GetFuel function
+ setCB(GetFuel)
+end)
+
+function SetFuelType(vehicle, fuelType)
+ if not DoesEntityExist(vehicle) then
+ warn(("[SetFuelType] Vehicle entity does not exist. Received: %s. This is usually caused by a misconfiguration in the export."):format(tostring(vehicle)))
+ return
+ end
+ if not fuelType or fuelType == "nil" or fuelType == "" then
+ fuelType = dealWithDefaultFuelType(vehicle, "default")
+ end
+ TriggerServerEvent("lc_fuel:setVehicleFuelType", GetVehicleNumberPlateText(vehicle), fuelType)
+end
+exports('SetFuelType', SetFuelType)
+
+function setFuelType(vehicle, fuelType)
+ return SetFuelType(vehicle, fuelType)
+end
+exports('setFuelType', setFuelType)
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Utils
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function getVehicleFuelTypeFromServer(vehicle)
+ local returnFuelType = nil
+
+ Utils.Callback.TriggerServerCallback('lc_fuel:getVehicleFuelType', function(fuelType)
+ returnFuelType = dealWithDefaultFuelType(vehicle, fuelType)
+ end, GetVehicleNumberPlateText(vehicle))
+
+ while returnFuelType == nil do
+ Wait(10)
+ end
+ return returnFuelType
+end
+
+function dealWithDefaultFuelType(vehicle, fuelType)
+ -- Define if the vehicle is diesel or gasoline for the ones that have never been refueled
+ if fuelType == "default" then
+ if IsVehicleDiesel(vehicle) then
+ fuelType = "diesel"
+ elseif IsVehicleElectric(vehicle) then
+ fuelType = "electric"
+ else
+ fuelType = "regular"
+ end
+ end
+ return fuelType
+end
+
+function changeVehicleFuelType(vehicle, fuelType)
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+ if vehicle and #(playerCoords - GetEntityCoords(vehicle)) < 5 then
+ SetFuel(vehicle, 0.0)
+ exports['lc_utils']:notify("info",Utils.translate("vehicle_tank_emptied"))
+ TriggerServerEvent("lc_fuel:setVehicleFuelType", GetVehicleNumberPlateText(vehicle), fuelType)
+ else
+ exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
+ end
+end
+
+function getVehicleDisplayFuelAmount(currentFuel, tankSize)
+ local displayFuelAmount = currentFuel * tankSize / 100
+ return displayFuelAmount
+end
+
+function getVehicleTankSize(vehicle)
+ local vehicleHash = GetEntityModel(vehicle)
+ if Config.FuelTankSize.perVehicleHash[vehicleHash] then
+ return Config.FuelTankSize.perVehicleHash[vehicleHash]
+ end
+ return Config.FuelTankSize.perClass[GetVehicleClass(vehicle)] or 100
+end
+
+function GetPumpOffset(pump)
+ local heightOffset = { forward = 0.0, right = 0.0, up = 2.1 }
+ local pumpModel = GetEntityModel(pump)
+
+ for _, v in pairs(Config.Electric.chargersProps) do
+ if pumpModel == joaat(v.prop) then
+ heightOffset = v.ropeOffset
+ end
+ end
+
+ for _, v in pairs(Config.GasPumpProps) do
+ if pumpModel == joaat(v.prop) then
+ heightOffset = v.ropeOffset
+ end
+ end
+
+ return heightOffset
+end
+
+function CreateRopeToPump(pumpCoords)
+ local offset = GetPumpOffset(currentPump)
+
+ RopeLoadTextures()
+ while not RopeAreTexturesLoaded() do
+ Wait(0)
+ end
+
+ local forwardVector, rightVector, upVector, _ = GetEntityMatrix(currentPump)
+
+ -- Adjust the offsets
+ local forwardOffset = forwardVector * offset.forward
+ local rightoffset = rightVector * offset.right
+ local upOffset = upVector * offset.up
+ local finalOffset = forwardOffset + rightoffset + upOffset
+
+ local ropeObj = AddRope(pumpCoords.x + finalOffset.x, pumpCoords.y + finalOffset.y, pumpCoords.z + finalOffset.z, 0.0, 0.0, 0.0, 4.0, 1, 10.0, 0.0, 1.0, false, false, false, 1.0, true)
+ while not ropeObj do
+ Wait(0)
+ end
+ ActivatePhysics(ropeObj)
+ Wait(100)
+
+ local nozzlePos = GetOffsetFromEntityInWorldCoords(fuelNozzle, 0.0, -0.033, -0.195)
+ ---@diagnostic disable-next-line: param-type-mismatch
+ AttachEntitiesToRope(ropeObj, currentPump, fuelNozzle, pumpCoords.x + finalOffset.x, pumpCoords.y + finalOffset.y, pumpCoords.z + finalOffset.z, nozzlePos.x, nozzlePos.y, nozzlePos.z, 30.0, false, false, nil, nil)
+ return ropeObj
+end
+
+function GetVehicles()
+ return GetGamePool('CVehicle')
+end
+
+function GetClosestVehicle(coords, modelFilter)
+ return GetClosestEntity(GetVehicles(), false, coords, modelFilter)
+end
+
+function GetClosestEntity(entities, isPlayerEntities, coords, modelFilter)
+ local closestEntity, closestEntityDistance, filteredEntities = -1, -1, nil
+
+ if coords then
+ coords = vector3(coords.x, coords.y, coords.z)
+ else
+ local playerPed = PlayerPedId()
+ coords = GetEntityCoords(playerPed)
+ end
+
+ if modelFilter then
+ filteredEntities = {}
+
+ for _, entity in pairs(entities) do
+ if modelFilter[GetEntityModel(entity)] then
+ filteredEntities[#filteredEntities + 1] = entity
+ end
+ end
+ end
+
+ for k, entity in pairs(filteredEntities or entities) do
+ local distance = #(coords - GetEntityCoords(entity))
+
+ if closestEntityDistance == -1 or distance < closestEntityDistance then
+ closestEntity, closestEntityDistance = isPlayerEntities and k or entity, distance
+ end
+ end
+
+ return closestEntity, closestEntityDistance
+end
+
+function GetVehicleCapPos(vehicle)
+ local closestCapPos
+ local tanks = vehicleCapBoneList()
+ for _, v in pairs(tanks) do
+ local vehicleTank = GetEntityBoneIndexByName(vehicle, v)
+ if vehicleTank ~= -1 then
+ closestCapPos = GetWorldPositionOfEntityBone(vehicle, vehicleTank)
+ break
+ end
+ end
+ return closestCapPos
+end
+
+function Round(num, numDecimalPlaces)
+ error("Do not use this")
+end
+
+function IsVehicleBlacklisted(vehicle)
+ if vehicle and vehicle ~= 0 then
+ local vehicleHash = GetEntityModel(vehicle)
+ -- Blacklist electric vehicles if electric recharge is disabled
+ if not Config.Electric.enabled and IsVehicleElectric(vehicle) then
+ return true
+ end
+
+ -- Check if the vehicle is in the blacklist
+ if Config.BlacklistedVehiclesHash[vehicleHash] then
+ return true
+ end
+ return false
+ end
+ return true
+end
+
+function IsVehicleDiesel(vehicle)
+ if vehicle and vehicle ~= 0 then
+ local vehicleHash = GetEntityModel(vehicle)
+ -- Check if the vehicle is in the diesel list
+ if Config.DieselVehiclesHash[vehicleHash] then
+ return true
+ end
+ end
+ return false
+end
+
+function IsVehicleElectric(vehicle)
+ if vehicle and vehicle ~= 0 then
+ local vehicleHash = GetEntityModel(vehicle)
+ -- Check if the vehicle is in the diesel list
+ if Config.Electric.vehiclesListHash[vehicleHash] then
+ return true
+ end
+ end
+ return false
+end
+
+function GetClosestPump(coords, isElectric)
+ local pump = nil
+ local currentPumpModel = nil
+ local pumpList = isElectric and Config.Electric.chargersProps or Config.GasPumpProps
+
+ for i = 1, #pumpList do
+ currentPumpModel = pumpList[i].prop
+ pump = GetClosestObjectOfType(coords.x, coords.y, coords.z, 2.5, joaat(currentPumpModel), true, true, true)
+ if pump ~= 0 then return pump, currentPumpModel end
+ end
+
+ return nil, nil
+end
+
+function createBlips()
+ if Config.Blips.onlyShowNearestBlip then
+ Citizen.CreateThread(function()
+ local currentBlip = 0
+ local currentBlipIndex = 0
+
+ while true do
+ local coords = GetEntityCoords(PlayerPedId())
+ local closestBlipDistance = math.maxinteger
+ local closestBlipCoords
+ local closestBlipId
+
+ for blipId, blipCoord in pairs(Config.Blips.locations) do
+ local distanceToBlip = #(coords - blipCoord)
+
+ if distanceToBlip < closestBlipDistance then
+ closestBlipDistance = distanceToBlip
+ closestBlipCoords = blipCoord
+ closestBlipId = blipId
+ end
+ end
+
+ if currentBlipIndex ~= closestBlipId then
+ if DoesBlipExist(currentBlip) then
+ Utils.Blips.removeBlip(currentBlip)
+ end
+
+ if closestBlipCoords then
+ currentBlip = Utils.Blips.createBlipForCoords(closestBlipCoords.x,closestBlipCoords.y,closestBlipCoords.z,Config.Blips.blipId,Config.Blips.color,Utils.translate('blip_text'),Config.Blips.scale,false)
+ end
+
+ currentBlipIndex = closestBlipId
+ end
+
+ Citizen.Wait(5000)
+ end
+ end)
+ else
+ local text = Utils.translate('blip_text')
+ for _, blipCoords in pairs(Config.Blips.locations) do
+ Utils.Blips.createBlipForCoords(blipCoords.x,blipCoords.y,blipCoords.z,Config.Blips.blipId,Config.Blips.color,text,Config.Blips.scale,false)
+ end
+ end
+end
+
+function convertConfigVehiclesDisplayNameToHash()
+ Config.BlacklistedVehiclesHash = {}
+ for _, value in pairs(Config.BlacklistedVehicles) do
+ Config.BlacklistedVehiclesHash[joaat(value)] = true
+ end
+ Config.Electric.vehiclesListHash = {}
+ for _, value in pairs(Config.Electric.vehiclesList) do
+ Config.Electric.vehiclesListHash[joaat(value)] = true
+ end
+ Config.DieselVehiclesHash = {}
+ for _, value in pairs(Config.DieselVehicles) do
+ Config.DieselVehiclesHash[joaat(value)] = true
+ end
+ Config.FuelTankSize.perVehicleHash = {}
+ for key, value in pairs(Config.FuelTankSize.perVehicle) do
+ Config.FuelTankSize.perVehicleHash[joaat(key)] = value
+ end
+ Config.CustomVehicleParametersHash = {}
+ Utils.Table.deepMerge(Config.HiddenCustomVehicleParameters, Config.CustomVehicleParameters)
+ for key, value in pairs(Config.HiddenCustomVehicleParameters) do
+ Config.CustomVehicleParametersHash[joaat(key)] = value
+ end
+ Config.CustomVehicleParametersHash.default = Config.CustomVehicleParameters.default -- Adds back the default
+end
+
+RegisterNetEvent('lc_fuel:Notify')
+AddEventHandler('lc_fuel:Notify', function(type,message)
+ exports['lc_utils']:notify(type,message)
+end)
+
+Citizen.CreateThread(function()
+ Wait(1000)
+ SetNuiFocus(false,false)
+ SetNuiFocusKeepInput(false)
+ FreezeEntityPosition(PlayerPedId(), false)
+
+ Utils.loadLanguageFile(Lang)
+
+ cachedTranslations = {
+ open_refuel = Utils.translate('markers.open_refuel'),
+ open_recharge = Utils.translate('markers.open_recharge'),
+ interact_with_vehicle = Utils.translate('markers.interact_with_vehicle'),
+ return_nozzle = Utils.translate('markers.return_nozzle'),
+ }
+
+ convertConfigVehiclesDisplayNameToHash()
+
+ if Config.Blips and Config.Blips.enabled then
+ createBlips()
+ end
+
+ -- Gas
+ if Utils.Config.custom_scripts_compatibility.target == "disabled" then
+ createGasMarkersThread()
+ else
+ createGasTargetsThread()
+ end
+ createCustomPumpModelsThread()
+
+ -- Electrics
+ if Config.Electric.enabled then
+ CreateThread(function()
+ createElectricZones()
+
+ if Utils.Config.custom_scripts_compatibility.target == "disabled" then
+ createElectricMarkersThread()
+ else
+ createElectricTargetsThread()
+ end
+ end)
+ end
+
+ -- Refuel
+ if Utils.Config.custom_scripts_compatibility.target ~= "disabled" then
+ createTargetForVehicleIteraction()
+ end
+
+ -- Other threads
+ createFuelConsumptionThread()
+ if Config.JerryCan.enabled and Utils.Config.custom_scripts_compatibility.target == "disabled" then
+ createJerryCanThread()
+ end
+
+ if Config.DebugNozzleOffset then
+ createDebugNozzleOffsetThread()
+ end
+end)
+
+-- Debug nozzle offset functions
+function GetVehiclePlayerIsLookingAt()
+ local playerPed = PlayerPedId()
+ local camCoords = GetGameplayCamCoord()
+ local camRot = GetGameplayCamRot(2)
+ local direction = RotationToDirection(camRot)
+ local maxDistance = 10.0
+
+ local destCoords = camCoords + direction * maxDistance
+ local rayHandle = StartShapeTestRay(camCoords.x, camCoords.y, camCoords.z, destCoords.x, destCoords.y, destCoords.z, 10, playerPed, 0)
+ local _, hit, endCoords, _, entityHit = GetShapeTestResult(rayHandle)
+
+ if hit == 1 and IsEntityAVehicle(entityHit) then
+ return entityHit
+ end
+ return nil
+end
+
+function GetLookAtHitCoords()
+ local playerPed = PlayerPedId()
+ local camCoords = GetGameplayCamCoord()
+ local camRot = GetGameplayCamRot(2)
+ local direction = RotationToDirection(camRot)
+
+ local endCoords = vec3(
+ camCoords.x + direction.x * 10.0,
+ camCoords.y + direction.y * 10.0,
+ camCoords.z + direction.z * 10.0
+ )
+
+ local rayHandle = StartShapeTestRay(camCoords.x, camCoords.y, camCoords.z, endCoords.x, endCoords.y, endCoords.z, -1, playerPed, 0)
+ local _, hit, hitCoords = GetShapeTestResult(rayHandle)
+ return hit, hitCoords
+end
+
+function RotationToDirection(rot)
+ local z = math.rad(rot.z)
+ local x = math.rad(rot.x)
+ local cosX = math.cos(x)
+
+ return vec3(
+ -math.sin(z) * cosX,
+ math.cos(z) * cosX,
+ math.sin(x)
+ )
+end
+
+-- Gets the offset from 'petrolcap' to the point you're looking at
+function GetNozzleOffset(vehicle, hitCoords)
+ -- World position of the bone
+ local boneWorldPos = GetVehicleCapPos(vehicle)
+
+ -- Directional vector from bone to hit point
+ local direction = {
+ x = hitCoords.x - boneWorldPos.x,
+ y = hitCoords.y - boneWorldPos.y,
+ z = hitCoords.z - boneWorldPos.z
+ }
+
+ -- Convert direction vector to vehicle-local offset
+ local forwardVector, rightVector, upVector, _ = GetEntityMatrix(vehicle)
+
+ local offset = {
+ right = direction.x * rightVector.x + direction.y * rightVector.y + direction.z * rightVector.z,
+ forward = direction.x * forwardVector.x + direction.y * forwardVector.y + direction.z * forwardVector.z,
+ up = direction.x * upVector.x + direction.y * upVector.y + direction.z * upVector.z
+ }
+
+ return offset
+end
+
+if Config.EnableHUD then
+ local function DrawAdvancedText(x,y ,w,h,sc, text, r,g,b,a,font,jus)
+ SetTextFont(font)
+ SetTextProportional(false)
+ SetTextScale(sc, sc)
+ SetTextJustification(jus)
+ SetTextColour(r, g, b, a)
+ SetTextDropShadow()
+ SetTextEdge(1, 0, 0, 0, 255)
+ SetTextDropShadow()
+ SetTextOutline()
+ SetTextEntry("STRING")
+ AddTextComponentString(text)
+ DrawText(x - 0.1+w, y - 0.02+h)
+ end
+
+ local mph = "0"
+ local kmh = "0"
+ local fuel = "0"
+ local displayHud = false
+
+ local x = 0.01135
+ local y = 0.002
+
+ Citizen.CreateThread(function()
+ while true do
+ local ped = PlayerPedId()
+
+ if IsPedInAnyVehicle(ped, false) then
+ local vehicle = GetVehiclePedIsIn(ped, false)
+ local speed = GetEntitySpeed(vehicle)
+
+ mph = tostring(math.ceil(speed * 2.236936))
+ kmh = tostring(math.ceil(speed * 3.6))
+ fuel = tostring(Utils.Math.round(GetVehicleFuelLevel(vehicle),2))
+
+ displayHud = true
+ else
+ displayHud = false
+
+ Citizen.Wait(500)
+ end
+
+ Citizen.Wait(50)
+ end
+ end)
+
+ Citizen.CreateThread(function()
+ while true do
+ if displayHud then
+ DrawAdvancedText(0.130 - x, 0.77 - y, 0.005, 0.0028, 0.6, mph, 255, 255, 255, 255, 6, 1)
+ DrawAdvancedText(0.174 - x, 0.77 - y, 0.005, 0.0028, 0.6, kmh, 255, 255, 255, 255, 6, 1)
+ DrawAdvancedText(0.2155 - x, 0.77 - y, 0.005, 0.0028, 0.6, fuel, 255, 255, 255, 255, 6, 1)
+ DrawAdvancedText(0.2615 - x, 0.77 - y, 0.005, 0.0028, 0.6, tostring(currentConsumption), 255, 255, 255, 255, 6, 1)
+ DrawAdvancedText(0.145 - x, 0.7765 - y, 0.005, 0.0028, 0.4, "mp/h km/h Fuel Consumption", 255, 255, 255, 255, 6, 1)
+ else
+ Citizen.Wait(50)
+ end
+
+ Citizen.Wait(0)
+ end
+ end)
+end
+
+AddEventHandler('onResourceStop', function(resourceName)
+ if GetCurrentResourceName() ~= resourceName then return end
+
+ deleteRopeAndNozzleProp()
+end)
+
+function deleteRopeAndNozzleProp()
+ if DoesRopeExist(fuelRope) then
+ RopeUnloadTextures()
+ DeleteRope(fuelRope)
+ end
+ if DoesEntityExist(fuelNozzle) then
+ DeleteEntity(fuelNozzle)
+ end
+end
+
+function vehicleCapBoneList()
+ return { "petrolcap", "petroltank", "petroltank_l", "petroltank_r", "wheel_lr", "wheel_lf", "engine", "chassis_dummy" }
+end
+
+-- Do not change this, use the Config.CustomVehicleParameters in config.lua
+Config.HiddenCustomVehicleParameters = {
+ -- Cars
+ ["asbo"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.21, up = 0.50} },
+ ["blista"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.21, up = 0.50} },
+ ["brioso"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.10, up = 0.60} },
+ ["club"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.13, up = 0.50} },
+ ["kanjo"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.17, up = 0.50} },
+ ["issi2"] = { distance = 1.2, nozzleOffset = { forward = -0.2, right = -0.15, up = 0.50} },
+ ["issi3"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.54} },
+ ["issi4"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
+ ["issi5"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
+ ["issi6"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.13, up = 0.70} },
+ ["panto"] = { distance = 1.2, nozzleOffset = { forward = -0.10, right = -0.15, up = 0.65} },
+ ["prairie"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.20, up = 0.45} },
+ ["rhapsody"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.20, up = 0.45} },
+ ["brioso2"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.13, up = 0.40} },
+ ["weevil"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.03, up = 0.63} },
+ ["issi7"] = { distance = 1.2, nozzleOffset = { forward = -0.03, right = -0.12, up = 0.57} },
+ ["blista2"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.23, up = 0.50} },
+ ["blista3"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.23, up = 0.50} },
+ ["brioso3"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.06, up = 0.40} },
+ ["boor"] = { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.18, up = 0.50} },
+ ["asea"] = { distance = 1.2, nozzleOffset = { forward = -0.28, right = -0.21, up = 0.50} },
+ ["asterope"] = { distance = 1.2, nozzleOffset = { forward = -0.28, right = -0.16, up = 0.50} },
+ ["cog55"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.21, up = 0.45} },
+ ["cognoscenti"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.21, up = 0.45} },
+ ["emperor"] = { distance = 1.2, nozzleOffset = { forward = -0.44, right = -0.22, up = 0.40} },
+ ["fugitive"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.40} },
+ ["glendale"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.40} },
+ ["glendale2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.30} },
+ ["ingot"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.45} },
+ ["intruder"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.40} },
+ ["premier"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.16, up = 0.52} },
+ ["primo"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.18, up = 0.40} },
+ ["primo2"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.20, up = 0.35} },
+ ["regina"] = { distance = 1.2, nozzleOffset = { forward = -0.52, right = -0.24, up = 0.40} },
+ ["stafford"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.17, up = 0.50} },
+ ["stanier"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.40} },
+ ["stratum"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.35} },
+ ["stretch"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.35} },
+ ["superd"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.40} },
+ ["tailgater"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.45} },
+ ["warrener"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.45} },
+ ["washington"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.22, up = 0.45} },
+ ["tailgater2"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.14, up = 0.45} },
+ ["cinquemila"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.21, up = 0.55} },
+ ["astron"] = { distance = 1.2, nozzleOffset = { forward = -0.20, right = -0.22, up = 0.55} },
+ ["baller7"] = { distance = 1.2, nozzleOffset = { forward = -0.62, right = -0.16, up = 0.60} },
+ ["comet7"] = { distance = 1.2, nozzleOffset = { forward = -0.37, right = -0.19, up = 0.45} },
+ ["deity"] = { distance = 1.2, nozzleOffset = { forward = -0.37, right = -0.21, up = 0.50} },
+ ["jubilee"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.60} },
+ ["oracle"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.40} },
+ ["schafter2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.45} },
+ ["warrener2"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.20, up = 0.40} },
+ ["rhinehart"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.15, up = 0.50} },
+ ["eudora"] = { distance = 1.2, nozzleOffset = { forward = 0.29, right = -0.38, up = 0.22} },
+
+ ["rebla"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.60} },
+ ["baller"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.23, up = 0.60} },
+ ["baller2"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
+ ["baller3"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
+ ["baller4"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
+ ["baller5"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
+ ["baller6"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.60} },
+ ["bjxl"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.60} },
+ ["cavalcade"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.65} },
+ ["cavalcade2"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.21, up = 0.65} },
+ ["contender"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.17, up = 0.50} },
+ ["dubsta"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.17, up = 0.70} },
+ ["dubsta2"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.17, up = 0.70} },
+ ["fq2"] = { distance = 1.2, nozzleOffset = { forward = -0.32, right = -0.23, up = 0.53} },
+ ["granger"] = { distance = 1.2, nozzleOffset = { forward = 0.65, right = -0.27, up = 0.60} },
+ ["granger2"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.26, up = 0.60} },
+ ["gresley"] = { distance = 1.2, nozzleOffset = { forward = 0.05, right = -0.17, up = 0.66} },
+ ["habanero"] = { distance = 1.2, nozzleOffset = { forward = -0.47, right = -0.17, up = 0.50} },
+ ["huntley"] = { distance = 1.2, nozzleOffset = { forward = 0.07, right = -0.24, up = 0.65} },
+ ["landstalker"] = { distance = 1.2, nozzleOffset = { forward = 0.40, right = -0.23, up = 0.60} },
+ ["landstalker2"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.24, up = 0.60} },
+ ["novak"] = { distance = 1.2, nozzleOffset = { forward = -0.25, right = -0.21, up = 0.60} },
+ ["patriot"] = { distance = 1.2, nozzleOffset = { forward = 0.2, right = -0.22, up = 0.75} },
+ ["patriot2"] = { distance = 1.2, nozzleOffset = { forward = 0.2, right = -0.22, up = 0.75} },
+ ["patriot3"] = { distance = 1.2, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.65} },
+ ["radi"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.17, up = 0.60} },
+ ["rocoto"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.60} },
+ ["seminole"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.65} },
+ ["seminole2"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.55} },
+ ["serrano"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.60} },
+ ["toros"] = { distance = 1.2, nozzleOffset = { forward = -0.26, right = -0.26, up = 0.68} },
+ ["xls"] = { distance = 1.2, nozzleOffset = { forward = -0.0, right = -0.20, up = 0.65} },
+
+ ["cogcabrio"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
+ ["exemplar"] = { distance = 1.2, nozzleOffset = { forward = -0.27, right = -0.19, up = 0.45} },
+ ["f620"] = { distance = 1.2, nozzleOffset = { forward = -0.29, right = -0.25, up = 0.40} },
+ ["felon"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.40} },
+ ["felon2"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.40} },
+ ["jackal"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
+ ["oracle2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
+ ["sentinel"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
+ ["sentinel2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.50} },
+ ["windsor"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
+ ["windsor2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.50} },
+ ["zion"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.50} },
+ ["zion2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.50} },
+ ["previon"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.50} },
+ ["champion"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.11, up = 0.40} },
+ ["futo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.15, up = 0.40} },
+ ["sentinel3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.30} },
+ ["kanjosj"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.45} },
+ ["postlude"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.15, up = 0.45} },
+ ["tahoma"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
+ ["broadway"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
+
+ ["blade"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.31, up = 0.40} },
+ ["buccaneer"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.40} },
+ ["chino"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.35} },
+ ["chino2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.25} },
+ ["clique"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.21, up = 0.25} },
+ ["coquette3"] = { distance = 1.2, nozzleOffset = { forward = 0.43, right = -0.31, up = 0.25} },
+ ["deviant"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["dominator"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["dominator2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["dominator3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.40} },
+ ["dominator4"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.40} },
+ ["dominator7"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
+ ["dominator8"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.40} },
+ ["dukes"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.31, up = 0.40} },
+ ["dukes2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.31, up = 0.40} },
+ ["dukes3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.40} },
+ ["faction"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.17, up = 0.40} },
+ ["faction2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.30} },
+ ["faction3"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.16, up = 0.70} },
+ ["ellie"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.05, up = 0.67} },
+ ["gauntlet"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.40} },
+ ["gauntlet2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.40} },
+ ["gauntlet3"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.50} },
+ ["gauntlet4"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.18, up = 0.45} },
+ ["gauntlet5"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.50} },
+ ["hermes"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.31, up = 0.20} },
+ ["hotknife"] = { distance = 1.2, nozzleOffset = { forward = 0.40, right = -0.00, up = 0.30} },
+ ["hustler"] = { distance = 1.2, nozzleOffset = { forward = -0.62, right = 0.05, up = 0.20} },
+ ["impaler"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.27, up = 0.35} },
+ ["impaler2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.24, up = 0.35} },
+ ["impaler3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.22, up = 0.45} },
+ ["impaler4"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
+ ["imperator"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
+ ["imperator2"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
+ ["imperator3"] = { distance = 1.2, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.65} },
+ ["lurcher"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.30, up = 0.35} },
+ ["nightshade"] = { distance = 1.2, nozzleOffset = { forward = -0.60, right = -0.07, up = 0.35} },
+ ["phoenix"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.35} },
+ ["picador"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.23, up = 0.45} },
+ ["ratloader2"] = { distance = 1.2, nozzleOffset = { forward = 1.05, right = -0.07, up = 0.35} },
+ ["ruiner"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
+ ["ruiner2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.35} },
+ ["sabregt"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.35} },
+ ["sabregt2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.30} },
+ ["slamvan"] = { distance = 1.2, nozzleOffset = { forward = 0.90, right = 0.03, up = 0.25} },
+ ["slamvan2"] = { distance = 1.2, nozzleOffset = { forward = 0.90, right = -0.18, up = 0.30} },
+ ["slamvan3"] = { distance = 1.2, nozzleOffset = { forward = 0.85, right = -0.03, up = 0.10} },
+ ["stalion"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
+ ["stalion2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
+ ["tampa"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.35} },
+ ["tulip"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.23, up = 0.35} },
+ ["vamos"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.25, up = 0.39} },
+ ["vigero"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.22, up = 0.39} },
+ ["virgo"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.22, up = 0.39} },
+ ["virgo2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.30} },
+ ["virgo3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.25, up = 0.30} },
+ ["voodoo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.29, up = 0.42} },
+ ["yosemite"] = { distance = 1.2, nozzleOffset = { forward = 1.20, right = -0.29, up = 0.25} },
+ ["yosemite2"] = { distance = 1.2, nozzleOffset = { forward = 1.22, right = -0.13, up = 0.35} },
+ ["buffalo4"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.22, up = 0.50} },
+ ["manana"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.30} },
+ ["manana2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.30} },
+ ["tampa2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.10, up = 0.30} },
+ ["ruiner4"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.19, up = 0.35} },
+ ["vigero2"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
+ ["weevil2"] = { distance = 1.2, nozzleOffset = { forward = 1.90, right = 0.15, up = 0.25} },
+ ["buffalo5"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.50} },
+ ["tulip2"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.24, up = 0.35} },
+ ["clique2"] = { distance = 1.2, nozzleOffset = { forward = 0.05, right = -0.26, up = 0.60} },
+ ["brigham"] = { distance = 1.2, nozzleOffset = { forward = 0.15, right = -0.30, up = 0.40} },
+ ["greenwood"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.21, up = 0.50} },
+
+ ["ardent"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.19, up = 0.35} },
+ ["btype"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.05, up = 0.78} },
+ ["btype2"] = { distance = 1.2, nozzleOffset = { forward = 0.36, right = 0.07, up = 0.55} },
+ ["btype3"] = { distance = 1.2, nozzleOffset = { forward = 0.25, right = -0.05, up = 0.78} },
+ ["casco"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.30} },
+ ["deluxo"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.13, up = 0.40} },
+ ["dynasty"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.40} },
+ ["fagaloa"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.21, up = 0.35} },
+ ["feltzer3"] = { distance = 1.2, nozzleOffset = { forward = -0.31, right = -0.13, up = 0.55} },
+ ["gt500"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.25} },
+ ["infernus2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.27, up = 0.35} },
+ ["jb700"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.35} },
+ ["jb7002"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.35} },
+ ["mamba"] = { distance = 1.2, nozzleOffset = { forward = -0.30, right = -0.13, up = 0.50} },
+ ["michelli"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.18, up = 0.30} },
+ ["monroe"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.30} },
+ ["nebula"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
+ ["peyote"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.26, up = 0.30} },
+ ["peyote3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.26, up = 0.30} },
+ ["pigalle"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
+ ["rapidgt3"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
+ ["retinue"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
+ ["retinue2"] = { distance = 1.2, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.30} },
+ ["savestra"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.15, up = 0.40} },
+ ["stinger"] = { distance = 1.2, nozzleOffset = { forward = -0.02, right = -0.13, up = 0.65} },
+ ["stingergt"] = { distance = 1.2, nozzleOffset = { forward = -0.55, right = -0.20, up = 0.30} },
+ ["stromberg"] = { distance = 1.2, nozzleOffset = { forward = -0.35, right = -0.23, up = 0.35} },
+ ["swinger"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
+ ["torero"] = { distance = 1.2, nozzleOffset = { forward = 0.75, right = -0.21, up = 0.35} },
+ ["tornado"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
+ ["tornado2"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
+ ["tornado5"] = { distance = 1.2, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.25} },
+ ["turismo2"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.23, up = 0.40} },
+ ["viseris"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.18, up = 0.40} },
+ ["z190"] = { distance = 1.2, nozzleOffset = { forward = -0.68, right = -0.10, up = 0.47} },
+ ["ztype"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.23, up = 0.30} },
+ ["zion3"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.23, up = 0.30} },
+ ["cheburek"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.30} },
+ ["toreador"] = { distance = 1.2, nozzleOffset = { forward = -0.40, right = -0.22, up = 0.35} },
+ ["peyote2"] = { distance = 1.2, nozzleOffset = { forward = -0.50, right = -0.28, up = 0.30} },
+ ["coquette2"] = { distance = 1.2, nozzleOffset = { forward = 0.43, right = -0.24, up = 0.25} },
+
+ ["alpha"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.21, up = 0.40} },
+ ["banshee"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.09, up = 0.40} },
+ ["bestiagts"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.25, up = 0.45} },
+ ["buffalo"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
+ ["buffalo2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
+ ["carbonizzare"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.27, up = 0.50} },
+ ["comet2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
+ ["comet3"] = { distance = 1.3, nozzleOffset = { forward = -0.52, right = -0.07, up = 0.20} },
+ ["comet4"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.35} },
+ ["comet5"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.35} },
+ ["coquette"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.25} },
+ ["coquette4"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.25} },
+ ["drafter"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.45} },
+ ["elegy"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.28, up = 0.30} },
+ ["elegy2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.18, up = 0.50} },
+ ["feltzer2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.15, up = 0.45} },
+ ["flashgt"] = { distance = 1.3, nozzleOffset = { forward = -0.31, right = -0.26, up = 0.50} },
+ ["furoregt"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.50} },
+ ["gb200"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.20, up = 0.40} },
+ ["komoda"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["italigto"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.27, up = 0.40} },
+ ["jugular"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.16, up = 0.55} },
+ ["jester"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.23, up = 0.35} },
+ ["jester2"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.23, up = 0.35} },
+ ["jester3"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.16, up = 0.40} },
+ ["kuruma"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.40} },
+ ["kuruma2"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.19, up = 0.40} },
+ ["locust"] = { distance = 1.3, nozzleOffset = { forward = 0.44, right = 0.00, up = 0.61} },
+ ["lynx"] = { distance = 1.3, nozzleOffset = { forward = 0.43, right = -0.24, up = 0.40} },
+ ["massacro"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.42} },
+ ["massacro2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.42} },
+ ["neo"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.23, up = 0.42} },
+ ["ninef"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
+ ["ninef2"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
+ ["omnis"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.31} },
+ ["paragon"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.25, up = 0.40} },
+ ["pariah"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.19, up = 0.45} },
+ ["penumbra"] = { distance = 1.3, nozzleOffset = { forward = -0.25, right = -0.19, up = 0.50} },
+ ["penumbra2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.40} },
+ ["rapidgt"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
+ ["rapidgt2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
+ ["raptor"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.40, up = 0.25} },
+ ["revolter"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.17, up = 0.45} },
+ ["ruston"] = { distance = 1.3, nozzleOffset = { forward = 0.53, right = -0.00, up = 0.53} },
+ ["schafter3"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
+ ["schafter4"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
+ ["schlagen"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.40} },
+ ["seven70"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.23, up = 0.30} },
+ ["specter"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.23, up = 0.30} },
+ ["streiter"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.08, up = 0.50} },
+ ["sugoi"] = { distance = 1.3, nozzleOffset = { forward = -0.25, right = -0.15, up = 0.50} },
+ ["sultan"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["sultan2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["surano"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.26, up = 0.40} },
+ ["tropos"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.08, up = 0.40} },
+ ["verlierer2"] = { distance = 1.3, nozzleOffset = { forward = 1.60, right = -0.19, up = 0.30} },
+ ["vstr"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.17, up = 0.55} },
+ ["zr350"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.21, up = 0.35} },
+ ["calico"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.16, up = 0.45} },
+ ["futo2"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.19, up = 0.35} },
+ ["euros"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.15, up = 0.55} },
+ ["remus"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.16, up = 0.45} },
+ ["comet6"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.35} },
+ ["growler"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.23, up = 0.45} },
+ ["vectre"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.17, up = 0.45} },
+ ["cypher"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.21, up = 0.45} },
+ ["sultan3"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.40} },
+ ["rt3000"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.45} },
+ ["sultanrs"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.13, up = 0.40} },
+ ["visione"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.10, up = 0.40} },
+ ["cheetah2"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.20, up = 0.35} },
+ ["stingertt"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.25, up = 0.35} },
+ ["sentinel4"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
+ ["sm722"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.35} },
+ ["tenf"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.23, up = 0.43} },
+ ["tenf2"] = { distance = 1.3, nozzleOffset = { forward = 0.43, right = -0.15, up = 0.43} },
+ ["everon2"] = { distance = 1.3, nozzleOffset = { forward = -1.03, right = -0.24, up = 0.50} },
+ ["issi8"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.21, up = 0.55} },
+ ["corsita"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.24, up = 0.30} },
+ ["gauntlet6"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.21, up = 0.31} },
+ ["coureur"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.22, up = 0.45} },
+ ["r300"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.26, up = 0.40} },
+ ["panthere"] = { distance = 1.3, nozzleOffset = { forward = -0.30, right = -0.14, up = 0.40} },
+
+ ["adder"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.19, up = 0.50} },
+ ["autarch"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.30} },
+ ["banshee2"] = { distance = 1.3, nozzleOffset = { forward = -0.55, right = -0.09, up = 0.40} },
+ ["bullet"] = { distance = 1.3, nozzleOffset = { forward = -0.00, right = -0.30, up = 0.05} },
+ ["cheetah"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.31, up = 0.35} },
+ ["entity2"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.35} },
+ ["entityxf"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.31, up = 0.35} },
+ ["emerus"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.28, up = 0.35} },
+ ["fmj"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.23, up = 0.30} },
+ ["furia"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.26, up = 0.35} },
+ ["gp1"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.30} },
+ ["infernus"] = { distance = 1.3, nozzleOffset = { forward = 0.91, right = -0.14, up = 0.65} },
+ ["italigtb"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.20, up = 0.35} },
+ ["italigtb2"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.20, up = 0.40} },
+ ["krieger"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.21, up = 0.25} },
+ ["le7b"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.35, up = 0.25} },
+ ["nero"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.25} },
+ ["nero2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.29, up = 0.25} },
+ ["osiris"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.25} },
+ ["penetrator"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.25, up = 0.25} },
+ ["pfister811"] = { distance = 1.3, nozzleOffset = { forward = 0.75, right = -0.28, up = 0.35} },
+ ["prototipo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.35} },
+ ["reaper"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.15, up = 0.35} },
+ ["s80"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.31, up = 0.30} },
+ ["sc1"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.25, up = 0.30} },
+ ["sheava"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.17, up = 0.35} },
+ ["t20"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.27, up = 0.30} },
+ ["taipan"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.25, up = 0.30} },
+ ["tempesta"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = -0.10, up = 0.60} },
+ ["thrax"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.22, up = 0.30} },
+ ["tigon"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.27, up = 0.30} },
+ ["turismor"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.30} },
+ ["tyrant"] = { distance = 1.3, nozzleOffset = { forward = 0.30, right = -0.29, up = 0.50} },
+ ["tyrus"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.26, up = 0.30} },
+ ["vacca"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.32, up = 0.35} },
+ ["vagner"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.29, up = 0.35} },
+ ["xa21"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.35} },
+ ["zentorno"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.29, up = 0.35} },
+ ["zorrusso"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.27, up = 0.35} },
+ ["ignus"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.32, up = 0.35} },
+ ["zeno"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.24, up = 0.35} },
+ ["deveste"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.21, up = 0.25} },
+ ["lm87"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.34, up = 0.25} },
+ ["torero2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.35} },
+ ["entity3"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.27, up = 0.25} },
+ ["virtue"] = { distance = 1.3, nozzleOffset = { forward = 0.45, right = -0.19, up = 0.35} },
+
+ ["bfinjection"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = 0.02, up = 0.35} },
+ ["bifta"] = { distance = 1.3, nozzleOffset = { forward = 0.03, right = -0.65, up = 0.10} },
+
+ -- offroad
+ ["blazer"] = { distance = 1.3, nozzleOffset = { forward = -0.08, right = -0.29, up = 0.20} },
+ ["blazer2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.25, up = 0.25} },
+ ["blazer3"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.25, up = 0.15} },
+ ["blazer4"] = { distance = 1.3, nozzleOffset = { forward = -0.00, right = -0.22, up = 0.12} },
+ ["blazer5"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.55, up = 0.25} },
+ ["brawler"] = { distance = 1.3, nozzleOffset = { forward = -0.16, right = -0.13, up = 0.90} },
+ ["caracara"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.80} },
+ ["caracara2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.80} },
+ ["dubsta3"] = { distance = 1.3, nozzleOffset = { forward = -0.75, right = -0.97, up = 0.40} },
+ ["dune"] = { distance = 1.3, nozzleOffset = { forward = 0.05, right = -0.65, up = 0.05} },
+ ["everon"] = { distance = 1.3, nozzleOffset = { forward = -0.80, right = -0.04, up = 0.80} },
+ ["freecrawler"] = { distance = 1.3, nozzleOffset = { forward = -0.10, right = -0.20, up = 1.00} },
+ ["hellion"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.17, up = 0.40} },
+ ["kalahari"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.17, up = 0.40} },
+ ["kamacho"] = { distance = 1.3, nozzleOffset = { forward = 1.05, right = -0.02, up = 0.60} },
+ ["mesa3"] = { distance = 1.3, nozzleOffset = { forward = 0.25, right = 0.02, up = 0.85} },
+ ["outlaw"] = { distance = 1.3, nozzleOffset = { forward = 0.60, right = -0.13, up = 0.70} },
+ ["rancherxl"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.50} },
+ ["rebel2"] = { distance = 1.3, nozzleOffset = { forward = 1.10, right = -0.09, up = 0.55} },
+ ["riata"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.02, up = 0.80} },
+ ["sandking"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.17, up = 0.70} },
+ ["sandking2"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.17, up = 0.70} },
+ ["trophytruck"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.10, up = 0.70} },
+ ["trophytruck2"] = { distance = 1.3, nozzleOffset = { forward = 0.90, right = -0.10, up = 0.70} },
+ ["vagrant"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = 0.15, up = 0.25} },
+ ["verus"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.30, up = 0.08} },
+ ["winky"] = { distance = 1.3, nozzleOffset = { forward = -1.00, right = -0.19, up = 0.50} },
+ ["yosemite3"] = { distance = 1.3, nozzleOffset = { forward = 0.83, right = -0.19, up = 0.50} },
+ ["mesa"] = { distance = 1.3, nozzleOffset = { forward = 0.30, right = -0.11, up = 0.66} },
+ ["ratel"] = { distance = 1.3, nozzleOffset = { forward = 0.61, right = 0.16, up = 1.11} },
+ ["l35"] = { distance = 1.3, nozzleOffset = { forward = 0.80, right = -0.17, up = 0.55} },
+ ["monstrociti"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.45} },
+ ["draugur"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.16, up = 0.80} },
+
+ -- truck
+ ["guardian"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.16, up = 0.40} },
+ ["mixer2"] = { distance = 1.3, nozzleOffset = { forward = 0.0, right = 0.11, up = -0.06} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["tiptruck2"] = { distance = 3.5, nozzleOffset = { forward = 2.00, right = -2.25, up = -0.24} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["tiptruck"] = { distance = 1.3, nozzleOffset = { forward = 0.01, right = -0.19, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["rubble"] = { distance = 1.3, nozzleOffset = { forward = 0.01, right = -0.19, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["mixer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.23, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["flatbed"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.23, up = 0.04} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dump"] = { distance = 1.3, nozzleOffset = { forward = 0.27, right = -0.57, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["bulldozer"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.25, up = 0.80} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["handler"] = { distance = 1.3, nozzleOffset = { forward = 0.88, right = -0.52, up = 0.88} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cutter"] = { distance = 1.3, nozzleOffset = { forward = 0.95, right = -0.42, up = 0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
+
+ -- utillity
+ ["slamtruck"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.26} },
+ ["utillitruck"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -1.25, up = 0.50} },
+ ["utillitruck2"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -1.25, up = 0.50} },
+ ["utillitruck3"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = -0.30, up = 0.50} },
+ ["tractor"] = { distance = 2.0, nozzleOffset = { forward = 1.50, right = 0.27, up = 0.30} },
+ ["tractor2"] = { distance = 2.0, nozzleOffset = { forward = 1.60, right = 0.05, up = 0.20} },
+ ["tractor3"] = { distance = 2.0, nozzleOffset = { forward = 1.60, right = 0.05, up = 0.20} },
+ ["towtruck"] = { distance = 2.0, nozzleOffset = { forward = -0.45, right = -0.30, up = 0.10} },
+ ["towtruck2"] = { distance = 2.0, nozzleOffset = { forward = 0.85, right = 0.05, up = 0.50} },
+ ["scrap"] = { distance = 2.0, nozzleOffset = { forward = -0.52, right = -0.05, up = -0.05} },
+ ["sadler"] = { distance = 1.3, nozzleOffset = { forward = 1.14, right = -0.22, up = 0.70} },
+ ["ripley"] = { distance = 2.0, nozzleOffset = { forward = -0.95, right = -0.48, up = 0.40} },
+ ["mower"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = 0.10, up = 0.63} },
+ ["forklift"] = { distance = 1.3, nozzleOffset = { forward = 0.05, right = -0.27, up = -0.40} },
+ ["docktug"] = { distance = 2.5, nozzleOffset = { forward = 0.0, right = -0.25, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+
+ -- van
+ ["bison"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.26} },
+ ["bobcatxl"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.28, up = 0.35} },
+ ["burrito3"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.25, up = 0.35} },
+ ["gburrito2"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.22, up = 0.35} },
+ ["rumpo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.25, up = 0.35} },
+ ["journey"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.34, up = 0.45} },
+ ["minivan"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.20, up = 0.45} },
+ ["minivan2"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.20, up = 0.45} },
+ ["paradise"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.23, up = 0.45} },
+ ["rumpo3"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.23, up = 0.45} },
+ ["speedo"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
+ ["speedo4"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
+ ["surfer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.29, up = 0.45} },
+ ["youga3"] = { distance = 1.3, nozzleOffset = { forward = 0.55, right = -0.18, up = 0.45} },
+ ["youga"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.23, up = 0.45} },
+ ["youga2"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.25, up = 0.40} },
+ ["youga4"] = { distance = 1.3, nozzleOffset = { forward = 0.35, right = -0.30, up = 0.40} },
+ ["moonbeam"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.28, up = 0.40} },
+ ["moonbeam2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
+ ["boxville"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
+ ["boxville2"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
+ ["boxville3"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
+ ["boxville4"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
+ ["boxville5"] = { distance = 1.3, nozzleOffset = { forward = -2.20, right = -0.30, up = 0.05} },
+ ["pony"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.40} },
+ ["pony2"] = { distance = 1.3, nozzleOffset = { forward = 0.40, right = -0.26, up = 0.40} },
+ ["journey2"] = { distance = 1.3, nozzleOffset = { forward = -0.65, right = -0.34, up = 0.45} },
+ ["surfer3"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.29, up = 0.45} },
+ ["speedo5"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
+ ["mule2"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
+ ["taco"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.45} },
+
+
+ -- Lspd, ems ....
+ ["riot"] = { distance = 2.5, nozzleOffset = { forward = -0.80, right = -1.30, up = 0.30} },
+ ["riot2"] = { distance = 1.3, nozzleOffset = { forward = -0.70, right = -0.09, up = 0.65} },
+ ["pbus"] = { distance = 1.3, nozzleOffset = { forward = -0.70, right = -0.30, up = 0.65} },
+ ["police"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
+ ["police2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.24, up = 0.50} },
+ ["police3"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
+ ["police4"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
+ ["sheriff"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.17, up = 0.50} },
+ ["sheriff2"] = { distance = 1.3, nozzleOffset = { forward = 0.70, right = -0.28, up = 0.60} },
+ ["policeold1"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.24, up = 0.60} },
+ ["policeold2"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.40} },
+ ["policet"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.26, up = 0.60} },
+ ["policeb"] = { distance = 1.3, nozzleOffset = { forward = -0.18, right = -0.18, up = 0.10}, nozzleRotation = { x = 0, y = 0, z = 60} },
+ ["polmav"] = { distance = 3.0, nozzleOffset = { forward = 0.12, right = -0.60, up = -0.45}, nozzleRotation = { x = 0, y = 0, z = 20} },
+ ["ambulance"] = { distance = 1.3, nozzleOffset = { forward = 2.95, right = -0.08, up = 0.50} },
+ ["firetruk"] = { distance = 1.3, nozzleOffset = { forward = 0.50, right = -0.32, up = 0.70} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["lguard"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
+ ["pranger"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
+ ["fbi"] = { distance = 1.3, nozzleOffset = { forward = -0.45, right = -0.24, up = 0.40} },
+ ["fbi2"] = { distance = 1.3, nozzleOffset = { forward = 0.67, right = -0.27, up = 0.57} },
+ ["predator"] = { distance = 3.5, nozzleOffset = { forward = 1.80, right = 1.58, up = 0.17}, nozzleRotation = { x = 0, y = 0, z = 180} },
+
+ -- Military
+ ["apc"] = { distance = 2.5, nozzleOffset = { forward = -0.80, right = -1.00, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["barracks"] = { distance = 3.5, nozzleOffset = { forward = 0.00, right = -0.25, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["barracks2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.28, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["barracks3"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.16, up = -0.03} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["chernobog"] = { distance = 2.5, nozzleOffset = { forward = 3.70, right = -0.20, up = 0.22} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["crusader"] = { distance = 1.5, nozzleOffset = { forward = 0.25, right = -0.11, up = 0.65} },
+ ["halftrack"] = { distance = 1.5, nozzleOffset = { forward = -0.60, right = -0.30, up = 0.90} },
+ ["khanjali"] = { distance = 1.5, nozzleOffset = { forward = -0.55, right = -0.80, up = 0.95} },
+ ["rhino"] = { distance = 1.5, nozzleOffset = { forward = -0.05, right = -0.52, up = 1.00} },
+ ["scarab"] = { distance = 1.5, nozzleOffset = { forward = 0.60, right = 0.15, up = 1.08} },
+ ["terbyte"] = { distance = 1.5, nozzleOffset = { forward = -0.700, right = -0.47, up = 0.65} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["vetir"] = { distance = 3.0, nozzleOffset = { forward = 1.25, right = 1.95, up = 0.40} , nozzleRotation = { x = 0, y = 0, z = 180} },
+
+ ["thruster"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = 0.40, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["minitank"] = { distance = 1.5, nozzleOffset = { forward = 0.05, right = -0.05, up = 0.49} },
+
+ -- Electric cars
+ ["voltic"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.45} },
+ ["voltic2"] = { distance = 1.3, nozzleOffset = { forward = -0.12, right = 0.12, up = 0.57} },
+ ["caddy"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.53} },
+ ["caddy2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.35} },
+ ["caddy3"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.09, up = 0.35} },
+ ["surge"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.45} },
+ ["iwagen"] = { distance = 1.3, nozzleOffset = { forward = -0.40, right = -0.16, up = 0.50} },
+ ["raiden"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.13, up = 0.50} },
+ ["airtug"] = { distance = 1.3, nozzleOffset = { forward = -0.20, right = -0.18, up = 0.47} },
+ ["neon"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.50} },
+ ["omnisegt"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.40} },
+ ["cyclone"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.45} },
+ ["tezeract"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.48} },
+ ["imorgon"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.16, up = 0.48} },
+ ["dilettante"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.48} },
+ ["dilettante2"] = { distance = 1.3, nozzleOffset = { forward = -0.05, right = -0.14, up = 0.48} },
+ ["khamelion"] = { distance = 1.3, nozzleOffset = { forward = -0.35, right = -0.20, up = 0.48} },
+
+ ["rcbandito"] = { distance = 1.3, nozzleOffset = { forward = -0.12, right = 0.12, up = 0.22} },
+
+
+ -- Motorcycles
+ ["akuma"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.20, up = 0.20} },
+ ["avarus"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["bagger"] = { distance = 1.1, nozzleOffset = { forward = -0.26, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["bati"] = { distance = 1.1, nozzleOffset = { forward = -0.15, right = -0.25, up = 0.20} },
+ ["bati2"] = { distance = 1.1, nozzleOffset = { forward = -0.15, right = -0.24, up = 0.20} },
+ ["bf400"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.24, up = 0.29} },
+ ["carbonrs"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.22, up = 0.20} },
+ ["chimera"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.00, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["cliffhanger"] = { distance = 1.1, nozzleOffset = { forward = -0.33, right = 0.05, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["daemon"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["daemon2"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["defiler"] = { distance = 1.1, nozzleOffset = { forward = 0.09, right = -0.23, up = 0.20} },
+ ["deathbike"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["deathbike2"] = { distance = 1.1, nozzleOffset = { forward = -0.25, right = 0.03, up = 0.07} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["deathbike3"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.03, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["diablous"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.06, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["diablous2"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.03, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["double"] = { distance = 1.1, nozzleOffset = { forward = 0.01, right = -0.22, up = 0.20} },
+ ["enduro"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.17, up = 0.25} },
+ ["esskey"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.20, up = 0.20} },
+ ["faggio"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = -0.28, up = 0.30} },
+ ["faggio2"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = 0.25, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["faggio3"] = { distance = 1.1, nozzleOffset = { forward = 0.20, right = 0.25, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["fcr"] = { distance = 1.1, nozzleOffset = { forward = -0.03, right = -0.21, up = 0.10} },
+ ["gargoyle"] = { distance = 1.1, nozzleOffset = { forward = -0.26, right = 0.03, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["hakuchou"] = { distance = 1.1, nozzleOffset = { forward = 0.05, right = -0.17, up = 0.10} },
+ ["hakuchou2"] = { distance = 1.1, nozzleOffset = { forward = 0.00, right = -0.19, up = 0.10} },
+ ["hexer"] = { distance = 1.1, nozzleOffset = { forward = -0.17, right = 0.04, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["innovation"] = { distance = 1.1, nozzleOffset = { forward = -0.23, right = 0.02, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["lectro"] = { distance = 1.1, nozzleOffset = { forward = -0.12, right = -0.20, up = 0.20} },
+ ["manchez"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.20, up = 0.10} },
+ ["nemesis"] = { distance = 1.1, nozzleOffset = { forward = -0.03, right = -0.17, up = 0.10} },
+ ["nightblade"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.05, up = 0.14} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["oppressor"] = { distance = 1.1, nozzleOffset = { forward = -0.27, right = 0.05, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["pcj"] = { distance = 1.1, nozzleOffset = { forward = 0.04, right = -0.20, up = 0.20} },
+ ["ratbike"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["ruffian"] = { distance = 1.1, nozzleOffset = { forward = 0.04, right = -0.19, up = 0.20} },
+ ["sanchez"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.22, up = 0.25} },
+ ["sanchez2"] = { distance = 1.1, nozzleOffset = { forward = -0.05, right = -0.22, up = 0.25} },
+ ["sanctus"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.08} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["shotaro"] = { distance = 1.1, nozzleOffset = { forward = 0.06, right = -0.25, up = 0.20} },
+ ["sovereign"] = { distance = 1.1, nozzleOffset = { forward = -0.07, right = -0.23, up = 0.15} },
+ ["stryder"] = { distance = 1.1, nozzleOffset = { forward = 0.06, right = -0.20, up = 0.15} },
+ ["thrust"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.25, up = 0.15} },
+ ["vader"] = { distance = 1.1, nozzleOffset = { forward = 0.10, right = -0.25, up = 0.20} },
+ ["vindicator"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.25, up = 0.15} },
+ ["vortex"] = { distance = 1.1, nozzleOffset = { forward = -0.02, right = -0.20, up = 0.12} },
+ ["wolfsbane"] = { distance = 1.1, nozzleOffset = { forward = -0.22, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["zombiea"] = { distance = 1.1, nozzleOffset = { forward = -0.14, right = 0.03, up = 0.11} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["zombieb"] = { distance = 1.1, nozzleOffset = { forward = -0.21, right = 0.03, up = 0.15} , nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["manchez2"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.10} },
+ ["shinobi"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.20} },
+ ["reever"] = { distance = 1.1, nozzleOffset = { forward = 0.09, right = -0.20, up = 0.10} },
+ ["manchez3"] = { distance = 1.1, nozzleOffset = { forward = -0.04, right = -0.22, up = 0.10} },
+
+ -- truck 2
+ ["pounder2"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.12, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["mule4"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
+ ["phantom3"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["hauler2"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = 0.02} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["phantom2"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["mule5"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
+ ["stockade"] = { distance = 3.0, nozzleOffset = { forward = -0.50, right = -1.36, up = 0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["pounder"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.12, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["phantom"] = { distance = 1.3, nozzleOffset = { forward = -0.60, right = -0.17, up = 0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["packer"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["mule"] = { distance = 1.3, nozzleOffset = { forward = -0.50, right = -0.35, up = 0.75} },
+ ["hauler"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = -0.17, up = -0.02} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["biff"] = { distance = 1.3, nozzleOffset = { forward = 0.0, right = 0.11, up = -0.06} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["benson"] = { distance = 1.3, nozzleOffset = { forward = 0.32, right = 0.40, up = 0.21} , nozzleRotation = { x = 0, y = 0, z = 180} },
+
+ --helicopters
+ ["conada2"] = { distance = 3.5, nozzleOffset = { forward = -0.10, right = -0.90, up = 0.20}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["akula"] = { distance = 3.5, nozzleOffset = { forward = -1.50, right = -0.65, up = -0.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["annihilator2"] = { distance = 3.5, nozzleOffset = { forward = -1.10, right = -1.25, up = -1.70}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["annihilator"] = { distance = 3.5, nozzleOffset = { forward = -1.20, right = -1.05, up = -1.70}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["havok"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.49, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["hunter"] = { distance = 3.5, nozzleOffset = { forward = -1.50, right = -0.69, up = -0.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["seasparrow"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["seasparrow2"] = { distance = 3.2, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["supervolito"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.87, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["supervolito2"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.87, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["swift"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.90, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["swift2"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.90, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["valkyrie"] = { distance = 2.5, nozzleOffset = { forward = 1.60, right = -1.21, up = -1.80}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["valkyrie2"] = { distance = 2.5, nozzleOffset = { forward = 1.60, right = -1.21, up = -1.80}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["volatus"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.86, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["savage"] = { distance = 3.5, nozzleOffset = { forward = -0.10, right = -1.09, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["buzzard2"] = { distance = 2.2, nozzleOffset = { forward = -1.10, right = -0.76, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 10} },
+ ["buzzard"] = { distance = 2.5, nozzleOffset = { forward = -1.10, right = -0.76, up = -1.30}, nozzleRotation = { x = 0, y = 0, z = 10} },
+ ["cargobob"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cargobob2"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cargobob3"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cargobob4"] = { distance = 4.0, nozzleOffset = { forward = -2.20, right = -1.29, up = -2.30}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["conada"] = { distance = 2.0, nozzleOffset = { forward = -0.09, right = -0.90, up = 0.20}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["frogger"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = -0.92, up = -0.90}, nozzleRotation = { x = 0, y = 0, z = 20} },
+ ["frogger2"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = -0.92, up = -0.90}, nozzleRotation = { x = 0, y = 0, z = 20} },
+ ["seasparrow3"] = { distance = 1.5, nozzleOffset = { forward = -0.10, right = -0.70, up = 0.00}, nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["skylift"] = { distance = 4.0, nozzleOffset = { forward = 4.95, right = 0.00, up = -3.50}, nozzleRotation = { x = 0, y = 0, z = 90} },
+ ["maverick"] = { distance = 3.5, nozzleOffset = { forward = 0.00, right = -0.90, up = -1.50}, nozzleRotation = { x = 0, y = 0, z = 20} },
+
+ -- Boats
+ ["toro"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.75, up = 0.48 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["toro2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.75, up = 0.48 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["patrolboat"] = { distance = 1.0, nozzleOffset = { forward = -0.30, right = 0.25, up = 0.20 } , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["longfin"] = { distance = 1.5, nozzleOffset = { forward = 0.90 , right = -1.40, up = 0.68} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["speeder"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.65 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["speeder2"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.65 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["tropic"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = -1.15, up = 0.71} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["tropic2"] = { distance = 2.0, nozzleOffset = { forward = 1.00, right = -1.15, up = 0.71} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["suntrap"] = { distance = 2.0, nozzleOffset = { forward = 0.55, right = -0.95, up = 0.93} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["squalo"] = { distance = 1.5, nozzleOffset = { forward = 0.0, right = -0.95, up = 0.57 } , nozzleRotation = { x = -60, y = 0, z = 90} },
+ ["marquis"] = { distance = 1.5, nozzleOffset = { forward = 0.50, right = -1.35, up = 1.36 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["jetmax"] = { distance = 2.0, nozzleOffset = { forward = 0.50, right = -0.90, up = 0.54 } , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["dinghy"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dinghy2"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dinghy3"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dinghy4"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dinghy5"] = { distance = 1.0, nozzleOffset = { forward = -0.20, right = -0.69, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+
+ -- Jet
+ ["seashark"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
+ ["seashark3"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
+ ["seashark2"] = { distance = 2.0, nozzleOffset = { forward = 0.89, right = 0.00, up = 0.42 } , nozzleRotation = { x = -60, y = 0, z = 90} },
+
+ -- Submarine
+ ["avisa"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = -1.30, up = 0.14 } , nozzleRotation = { x = -85, y = 0, z = 90} },
+ ["submersible2"] = { distance = 2.5, nozzleOffset = { forward = -0.40, right = -0.70, up = 1.20 } , nozzleRotation = { x = -90, y = 0, z = 0} },
+ ["submersible"] = { distance = 2.5, nozzleOffset = { forward = -0.60, right = -0.85, up = 1.20 } , nozzleRotation = { x = -90, y = 0, z = 0} },
+
+ -- Big boats
+-- ["kosatka"] = { distance = 6.0, nozzleOffset = { forward = 0.0, right = -0.15, up = 1.0 } }, ----- BIG SUBMARINE
+ ["tug"] = { distance = 2.5, nozzleOffset = { forward = 0.0, right = 0.79, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 180} },
+
+ -- Plane
+ ["streamer216"] = { distance = 1.5, nozzleOffset = { forward = -0.40, right = 1.02, up = 1.10 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["raiju"] = { distance = 3.0, nozzleOffset = { forward = 1.0, right = -0.85, up = -0.25 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["alkonost"] = { distance = 11.0, nozzleOffset = { forward = -2.60, right = -5.30, up = 0.90 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["strikeforce"] = { distance = 3.0, nozzleOffset = { forward = 3.0, right = 1.37, up = 1.60 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["blimp3"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["avenger"] = { distance = 2.0, nozzleOffset = { forward = -0.60, right = -0.73, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["avenger2"] = { distance = 2.0, nozzleOffset = { forward = -0.60, right = -0.73, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["volatol"] = { distance = 2.0, nozzleOffset = { forward = 0.80, right = 0.46, up = 1.85} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["nokota"] = { distance = 2.5, nozzleOffset = { forward = -1.50, right = 1.60, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["seabreeze"] = { distance = 2.5, nozzleOffset = { forward = -0.20, right = -0.10, up = -1.70} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["pyro"] = { distance = 3.0, nozzleOffset = { forward = 2.10, right = 1.56, up = 0.90} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["mogul"] = { distance = 2.0, nozzleOffset = { forward = 0.30, right = -0.68, up = 1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["howard"] = { distance = 2.5, nozzleOffset = { forward = 1.80, right = 1.25, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["bombushka"] = { distance = 2.5, nozzleOffset = { forward = 0.50, right = -0.71, up = 1.25} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["molotok"] = { distance = 3.5, nozzleOffset = { forward = 2.00, right = -0.85, up = 0.55} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["microlight"] = { distance = 3.5, nozzleOffset = { forward = -0.02, right = 0.48, up = 0.30} , nozzleRotation = { x = 0, y = 0, z = 45} },
+ ["tula"] = { distance = 3.5, nozzleOffset = { forward = 0.70, right = -0.52, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["rogue"] = { distance = 3.5, nozzleOffset = { forward = 0.10, right = -0.15, up = 0.45} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["starling"] = { distance = 3.5, nozzleOffset = { forward = 0.10, right = -0.08, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["alphaz1"] = { distance = 3.5, nozzleOffset = { forward = -1.00, right = -0.03, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["nimbus"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = -0.10, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["luxor2"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = 0.80, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["velum2"] = { distance = 5.0, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["hydra"] = { distance = 2.5, nozzleOffset = { forward = -1.80, right = 1.88, up = 1.35} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["blimp2"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["dodo"] = { distance = 2.0, nozzleOffset = { forward = -0.15, right = -0.13, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["miljet"] = { distance = 6.0, nozzleOffset = { forward = 2.75, right = -0.47, up = -1.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["vestra"] = { distance = 2.5, nozzleOffset = { forward = 2.50, right = 1.35, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cargoplane"] = { distance = 2.5, nozzleOffset = { forward = 1.50, right = 0.27, up = 1.60} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["velum"] = { distance = 5.0, nozzleOffset = { forward = -0.30, right = -0.20, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["titan"] = { distance = 2.5, nozzleOffset = { forward = 0.50, right = -0.46, up = 1.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["shamal"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.10, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["lazer"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.09, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["stunt"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.08, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["luxor"] = { distance = 5.0, nozzleOffset = { forward = 0.00, right = 0.80, up = -0.30} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["jet"] = { distance = 15.0, nozzleOffset = { forward = 1.20, right = 1.20, up = 2.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["duster"] = { distance = 2.5, nozzleOffset = { forward = -0.20, right = -0.15, up = -0.05} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["cuban800"] = { distance = 2.5, nozzleOffset = { forward = 1.00, right = 0.51, up = 0.20} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["blimp"] = { distance = 2.0, nozzleOffset = { forward = -0.40, right = 0.41, up = 0.50 } , nozzleRotation = { x = 0, y = 0, z = 0} },
+
+ -- Service
+ ["brickade"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = 0.16, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["brickade2"] = { distance = 1.3, nozzleOffset = { forward = 0.00, right = 0.16, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
+ ["pbus2"] = { distance = 3.0, nozzleOffset = { forward = -2.38, right = -0.30, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["wastelander"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.05, up = -0.10} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["rallytruck"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} },
+-- ["metrotrain"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, --- metro
+-- ["freight"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, -- train
+-- ["cablecar"] = { distance = 2.0, nozzleOffset = { forward = 0.00, right = 0.64, up = 0.0} , nozzleRotation = { x = 0, y = 0, z = 180} }, -- cablecar
+ ["trash"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.15, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["trash2"] = { distance = 2.5, nozzleOffset = { forward = 0.00, right = -0.15, up = 0.00} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["tourbus"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.33, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["taxi"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.20, up = 0.45} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["rentalbus"] = { distance = 2.0, nozzleOffset = { forward = -0.50, right = -0.33, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["coach"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.29, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["bus"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.28, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+ ["airbus"] = { distance = 2.0, nozzleOffset = { forward = -0.80, right = -0.28, up = 0.50} , nozzleRotation = { x = 0, y = 0, z = 0} },
+
+ -- Race
+ ["openwheel2"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.60, up = 0.30} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["openwheel1"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.60, up = 0.35} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["formula2"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.50, up = 0.29} , nozzleRotation = { x = -75, y = 0, z = 90} },
+ ["formula"] = { distance = 2.0, nozzleOffset = { forward = 0.0, right = -0.50, up = 0.29} , nozzleRotation = { x = -75, y = 0, z = 90} },
+}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client_electric.lua b/resources/[carscripts]/lc_fuel/client/client_electric.lua
index af2dcee32..58da345e9 100644
--- a/resources/[carscripts]/lc_fuel/client/client_electric.lua
+++ b/resources/[carscripts]/lc_fuel/client/client_electric.lua
@@ -1,153 +1,153 @@
--- Do not load anything here if electric is disabled
-if not Config.Electric.enabled then
- return
-end
-
-local electricChargers = {}
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Threads
------------------------------------------------------------------------------------------------------------------------------------------
-
--- Create sphere zones for each station, hooking up onEnter/onExit
-function createElectricZones()
- assert(Utils.Zones, "You are using an outdated version of lc_utils. Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip")
-
- local stations = groupChargersByStation()
-
- for _, station in pairs(stations) do
- Utils.Zones.createZone({
- coords = station.center,
- radius = 50.0,
- onEnter = function()
- for _, charger in pairs(station.chargers) do
- loadElectricCharger(charger)
- end
- end,
- onExit = function()
- for _, charger in pairs(station.chargers) do
- unloadElectricCharger(charger)
- end
- end
- })
- end
-end
-
--- Thread to detect near electric chargers
-function createElectricMarkersThread()
- CreateThread(function()
- while true do
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
- local pump, pumpModel = GetClosestPump(playerCoords, true)
-
- while pump and pump > 0 and #(playerCoords - GetEntityCoords(pump)) < 2.0 do
- playerCoords = GetEntityCoords(ped)
- if not mainUiOpen and not DoesEntityExist(fuelNozzle) then
- Utils.Markers.showHelpNotification(cachedTranslations.open_recharge, true)
- if IsControlJustPressed(0,38) then
- clientOpenUI(pump, pumpModel, true)
- end
- end
- Wait(2)
- end
- Wait(1000)
- end
- end)
-end
-
-function createElectricTargetsThread()
- local pumpModels = {} -- This will be the final list without duplicates
- local seenModels = {} -- This acts as a set to track unique values
-
- for _, chargerData in pairs(Config.Electric.chargersLocation) do
- local model = chargerData.prop
- if not seenModels[model] then
- seenModels[model] = true -- Mark model as seen
- table.insert(pumpModels, model) -- Insert only if it's not a duplicate
- end
- end
-
- -- Pass unique models to the target creation function
- Utils.Target.createTargetForModel(pumpModels, openElectricUICallback, Utils.translate('target.open_recharge'), "fas fa-plug", "#00a413",nil,nil,canOpenPumpUiTargetCallback)
-
- Utils.Target.createTargetForModel(pumpModels,returnNozzle,Utils.translate('target.return_nozzle'),"fas fa-plug","#a42100",nil,nil,canReturnNozzleTargetCallback)
-end
-
-function openElectricUICallback()
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
- local pump, pumpModel = GetClosestPump(playerCoords, true)
- if pump then
- clientOpenUI(pump, pumpModel, true)
- else
- exports['lc_utils']:notify("error", Utils.translate("pump_not_found"))
- end
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Utils
------------------------------------------------------------------------------------------------------------------------------------------
-
-function loadElectricCharger(chargerData)
- if not electricChargers[chargerData.location] then
- RequestModel(chargerData.prop)
- while not HasModelLoaded(chargerData.prop) do
- Wait(10)
- end
-
- local heading = chargerData.location.w + 180.0
- local electricCharger = CreateObject(chargerData.prop, chargerData.location.x, chargerData.location.y, chargerData.location.z, false, true, true)
- SetEntityHeading(electricCharger, heading)
- FreezeEntityPosition(electricCharger, true)
-
- electricChargers[chargerData.location] = electricCharger
- end
-end
-
-function unloadElectricCharger(chargerData)
- local charger = electricChargers[chargerData.location]
- if charger and DoesEntityExist(charger) then
- DeleteEntity(charger)
- electricChargers[chargerData.location] = nil
- end
-end
-
--- Utility to group chargers by their station
-function groupChargersByStation()
- local stations = {}
- for _, charger in pairs(Config.Electric.chargersLocation) do
- local assigned = false
- for _, station in pairs(stations) do
- local dist = #(station.center - vector3(charger.location.x, charger.location.y, charger.location.z))
- if dist < 20.0 then
- table.insert(station.chargers, charger)
- station.center = (station.center + vector3(charger.location.x, charger.location.y, charger.location.z)) / 2
- assigned = true
- break
- end
- end
- if not assigned then
- table.insert(stations, {
- center = vector3(charger.location.x, charger.location.y, charger.location.z),
- chargers = { charger }
- })
- end
- end
- return stations
-end
-
-AddEventHandler('onResourceStop', function(resourceName)
- if GetCurrentResourceName() ~= resourceName then return end
-
- deleteAllElectricChargers()
-end)
-
-function deleteAllElectricChargers()
- for _, charger in pairs(electricChargers) do
- if DoesEntityExist(charger) then
- DeleteEntity(charger)
- end
- end
- electricChargers = {}
+-- Do not load anything here if electric is disabled
+if not Config.Electric.enabled then
+ return
+end
+
+local electricChargers = {}
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Threads
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+-- Create sphere zones for each station, hooking up onEnter/onExit
+function createElectricZones()
+ assert(Utils.Zones, "You are using an outdated version of lc_utils. Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip")
+
+ local stations = groupChargersByStation()
+
+ for _, station in pairs(stations) do
+ Utils.Zones.createZone({
+ coords = station.center,
+ radius = 50.0,
+ onEnter = function()
+ for _, charger in pairs(station.chargers) do
+ loadElectricCharger(charger)
+ end
+ end,
+ onExit = function()
+ for _, charger in pairs(station.chargers) do
+ unloadElectricCharger(charger)
+ end
+ end
+ })
+ end
+end
+
+-- Thread to detect near electric chargers
+function createElectricMarkersThread()
+ CreateThread(function()
+ while true do
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+ local pump, pumpModel = GetClosestPump(playerCoords, true)
+
+ while pump and pump > 0 and #(playerCoords - GetEntityCoords(pump)) < 2.0 do
+ playerCoords = GetEntityCoords(ped)
+ if not mainUiOpen and not DoesEntityExist(fuelNozzle) then
+ Utils.Markers.showHelpNotification(cachedTranslations.open_recharge, true)
+ if IsControlJustPressed(0,38) then
+ clientOpenUI(pump, pumpModel, true)
+ end
+ end
+ Wait(2)
+ end
+ Wait(1000)
+ end
+ end)
+end
+
+function createElectricTargetsThread()
+ local pumpModels = {} -- This will be the final list without duplicates
+ local seenModels = {} -- This acts as a set to track unique values
+
+ for _, chargerData in pairs(Config.Electric.chargersLocation) do
+ local model = chargerData.prop
+ if not seenModels[model] then
+ seenModels[model] = true -- Mark model as seen
+ table.insert(pumpModels, model) -- Insert only if it's not a duplicate
+ end
+ end
+
+ -- Pass unique models to the target creation function
+ Utils.Target.createTargetForModel(pumpModels, openElectricUICallback, Utils.translate('target.open_recharge'), "fas fa-plug", "#00a413",nil,nil,canOpenPumpUiTargetCallback)
+
+ Utils.Target.createTargetForModel(pumpModels,returnNozzle,Utils.translate('target.return_nozzle'),"fas fa-plug","#a42100",nil,nil,canReturnNozzleTargetCallback)
+end
+
+function openElectricUICallback()
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+ local pump, pumpModel = GetClosestPump(playerCoords, true)
+ if pump then
+ clientOpenUI(pump, pumpModel, true)
+ else
+ exports['lc_utils']:notify("error", Utils.translate("pump_not_found"))
+ end
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Utils
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function loadElectricCharger(chargerData)
+ if not electricChargers[chargerData.location] then
+ RequestModel(chargerData.prop)
+ while not HasModelLoaded(chargerData.prop) do
+ Wait(10)
+ end
+
+ local heading = chargerData.location.w + 180.0
+ local electricCharger = CreateObject(chargerData.prop, chargerData.location.x, chargerData.location.y, chargerData.location.z, false, true, true)
+ SetEntityHeading(electricCharger, heading)
+ FreezeEntityPosition(electricCharger, true)
+
+ electricChargers[chargerData.location] = electricCharger
+ end
+end
+
+function unloadElectricCharger(chargerData)
+ local charger = electricChargers[chargerData.location]
+ if charger and DoesEntityExist(charger) then
+ DeleteEntity(charger)
+ electricChargers[chargerData.location] = nil
+ end
+end
+
+-- Utility to group chargers by their station
+function groupChargersByStation()
+ local stations = {}
+ for _, charger in pairs(Config.Electric.chargersLocation) do
+ local assigned = false
+ for _, station in pairs(stations) do
+ local dist = #(station.center - vector3(charger.location.x, charger.location.y, charger.location.z))
+ if dist < 20.0 then
+ table.insert(station.chargers, charger)
+ station.center = (station.center + vector3(charger.location.x, charger.location.y, charger.location.z)) / 2
+ assigned = true
+ break
+ end
+ end
+ if not assigned then
+ table.insert(stations, {
+ center = vector3(charger.location.x, charger.location.y, charger.location.z),
+ chargers = { charger }
+ })
+ end
+ end
+ return stations
+end
+
+AddEventHandler('onResourceStop', function(resourceName)
+ if GetCurrentResourceName() ~= resourceName then return end
+
+ deleteAllElectricChargers()
+end)
+
+function deleteAllElectricChargers()
+ for _, charger in pairs(electricChargers) do
+ if DoesEntityExist(charger) then
+ DeleteEntity(charger)
+ end
+ end
+ electricChargers = {}
end
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client_fuel_chart.lua b/resources/[carscripts]/lc_fuel/client/client_fuel_chart.lua
index 5822a04e0..355ea103e 100644
--- a/resources/[carscripts]/lc_fuel/client/client_fuel_chart.lua
+++ b/resources/[carscripts]/lc_fuel/client/client_fuel_chart.lua
@@ -1,77 +1,77 @@
-
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Fuel consumption chart
------------------------------------------------------------------------------------------------------------------------------------------
-
-if Config.FuelConsumptionChart.enabled then
- RegisterCommand(Config.FuelConsumptionChart.command,function(source)
- toggleFuelConsumptionChart()
- end, false)
-
- RegisterCommand("fuel_focus", function()
- if isFuelConsumptionChartOpen then
- SetNuiFocus(true,true)
- end
- end, false)
-
- RegisterKeyMapping(
- "fuel_focus", -- command triggered by key
- "Focus Fuel Chart UI", -- description in keybindings
- "keyboard",
- Config.FuelConsumptionChart.focusShortcut
- )
-
- function toggleFuelConsumptionChart()
- loadNuiVariables()
- if isFuelConsumptionChartOpen then
- closeFuelConsumptionChartUI()
- else
- local ped = PlayerPedId()
- if not IsPedInAnyVehicle(ped, false) then
- exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
- return
- end
- local vehicle = GetVehiclePedIsIn(ped, false)
- if GetPedInVehicleSeat(vehicle, -1) ~= ped or IsVehicleBlacklisted(vehicle) then
- exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
- return
- end
-
- SendNUIMessage({
- showFuelConsumptionChart = true,
- isRecording = isRecording,
- position = Config.FuelConsumptionChart.position,
- focusShortcut = Config.FuelConsumptionChart.focusShortcut,
- })
- isFuelConsumptionChartOpen = true
- end
- end
-
- function updateFuelConsumptionChart(fuelConsumptionData)
- SendNUIMessage({
- updateFuelConsumptionChart = true,
- fuelConsumptionData = fuelConsumptionData,
- })
- end
-
- function closeFuelConsumptionChartUI()
- SendNUIMessage({
- hideFuelConsumptionChart = true,
- })
- isFuelConsumptionChartOpen = false
- SetNuiFocus(false,false)
- end
-
- function storeDataForChart(vehicle, newFuelLevel, currentConsumption)
- if not isRecording then
- updateFuelConsumptionChart({ fuel = nil, speed = nil, consumption = nil })
- return
- end
-
- local speed = GetEntitySpeed(vehicle) * 3.6
- if isFuelConsumptionChartOpen then
- updateFuelConsumptionChart({ fuel = newFuelLevel, speed = speed, consumption = currentConsumption })
- end
- end
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Fuel consumption chart
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+if Config.FuelConsumptionChart.enabled then
+ RegisterCommand(Config.FuelConsumptionChart.command,function(source)
+ toggleFuelConsumptionChart()
+ end, false)
+
+ RegisterCommand("fuel_focus", function()
+ if isFuelConsumptionChartOpen then
+ SetNuiFocus(true,true)
+ end
+ end, false)
+
+ RegisterKeyMapping(
+ "fuel_focus", -- command triggered by key
+ "Focus Fuel Chart UI", -- description in keybindings
+ "keyboard",
+ Config.FuelConsumptionChart.focusShortcut
+ )
+
+ function toggleFuelConsumptionChart()
+ loadNuiVariables()
+ if isFuelConsumptionChartOpen then
+ closeFuelConsumptionChartUI()
+ else
+ local ped = PlayerPedId()
+ if not IsPedInAnyVehicle(ped, false) then
+ exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
+ return
+ end
+ local vehicle = GetVehiclePedIsIn(ped, false)
+ if GetPedInVehicleSeat(vehicle, -1) ~= ped or IsVehicleBlacklisted(vehicle) then
+ exports['lc_utils']:notify("error",Utils.translate("vehicle_not_found"))
+ return
+ end
+
+ SendNUIMessage({
+ showFuelConsumptionChart = true,
+ isRecording = isRecording,
+ position = Config.FuelConsumptionChart.position,
+ focusShortcut = Config.FuelConsumptionChart.focusShortcut,
+ })
+ isFuelConsumptionChartOpen = true
+ end
+ end
+
+ function updateFuelConsumptionChart(fuelConsumptionData)
+ SendNUIMessage({
+ updateFuelConsumptionChart = true,
+ fuelConsumptionData = fuelConsumptionData,
+ })
+ end
+
+ function closeFuelConsumptionChartUI()
+ SendNUIMessage({
+ hideFuelConsumptionChart = true,
+ })
+ isFuelConsumptionChartOpen = false
+ SetNuiFocus(false,false)
+ end
+
+ function storeDataForChart(vehicle, newFuelLevel, currentConsumption)
+ if not isRecording then
+ updateFuelConsumptionChart({ fuel = nil, speed = nil, consumption = nil })
+ return
+ end
+
+ local speed = GetEntitySpeed(vehicle) * 3.6
+ if isFuelConsumptionChartOpen then
+ updateFuelConsumptionChart({ fuel = newFuelLevel, speed = speed, consumption = currentConsumption })
+ end
+ end
end
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client_fuel_type.lua b/resources/[carscripts]/lc_fuel/client/client_fuel_type.lua
new file mode 100644
index 000000000..6ab57642b
--- /dev/null
+++ b/resources/[carscripts]/lc_fuel/client/client_fuel_type.lua
@@ -0,0 +1,10 @@
+RegisterCommand(Config.FuelTypeCommand, function()
+ local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+ if not DoesEntityExist(vehicle) then
+ exports['lc_utils']:notify("error", Utils.translate("vehicle_not_found"))
+ return
+ end
+
+ local fuelType = getVehicleFuelTypeFromServer(vehicle)
+ exports['lc_utils']:notify("info", Utils.translate("fuel_types.type_title"):format(Utils.translate("fuel_types."..fuelType)))
+end, false)
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client_gas.lua b/resources/[carscripts]/lc_fuel/client/client_gas.lua
index 149bf37f5..579d9584d 100644
--- a/resources/[carscripts]/lc_fuel/client/client_gas.lua
+++ b/resources/[carscripts]/lc_fuel/client/client_gas.lua
@@ -1,140 +1,140 @@
-local customGasPumps = {}
------------------------------------------------------------------------------------------------------------------------------------------
--- Threads
------------------------------------------------------------------------------------------------------------------------------------------
-
--- Thread to detect near fuel pumps
-function createGasMarkersThread()
- CreateThread(function()
- while true do
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
- local pump, pumpModel = GetClosestPump(playerCoords, false)
-
- while pump and pump > 0 and #(playerCoords - GetEntityCoords(pump)) < 2.0 do
- playerCoords = GetEntityCoords(ped)
- if not mainUiOpen and not DoesEntityExist(fuelNozzle) then
- Utils.Markers.showHelpNotification(cachedTranslations.open_refuel, true)
- if IsControlJustPressed(0,38) then
- clientOpenUI(pump, pumpModel, false)
- end
- end
- Wait(2)
- end
- Wait(1000)
- end
- end)
-end
-
-function createGasTargetsThread()
- local pumpModels = {}
- for _, v in pairs(Config.GasPumpProps) do
- table.insert(pumpModels, v.prop)
- end
- Utils.Target.createTargetForModel(pumpModels,openFuelUICallback,Utils.translate('target.open_refuel'),"fas fa-gas-pump","#a42100",nil,nil,canOpenPumpUiTargetCallback)
-
- Utils.Target.createTargetForModel(pumpModels,returnNozzle,Utils.translate('target.return_nozzle'),"fas fa-gas-pump","#a42100",nil,nil,canReturnNozzleTargetCallback)
-end
-
-function openFuelUICallback()
- local ped = PlayerPedId()
- local playerCoords = GetEntityCoords(ped)
- local pump, pumpModel = GetClosestPump(playerCoords, false)
- if pump then
- clientOpenUI(pump, pumpModel, false)
- else
- exports['lc_utils']:notify("error", Utils.translate("pump_not_found"))
- end
-end
-
-function createCustomPumpModelsThread()
- for _, pumpConfig in pairs(Config.CustomGasPumpLocations) do
- RequestModel(pumpConfig.prop)
-
- while not HasModelLoaded(pumpConfig.prop) do
- Wait(50)
- end
-
- local heading = pumpConfig.location.w + 180.0
- local gasPump = CreateObject(pumpConfig.prop, pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z, false, true, true)
- SetEntityHeading(gasPump, heading)
- FreezeEntityPosition(gasPump, true)
- table.insert(customGasPumps, gasPump)
- end
-end
-
-AddEventHandler('onResourceStop', function(resourceName)
- if GetCurrentResourceName() ~= resourceName then return end
-
- deleteAllCustomGasPumps()
-end)
-
-function deleteAllCustomGasPumps()
- for k, v in ipairs(customGasPumps) do
- DeleteEntity(v)
- end
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Jerry Cans
------------------------------------------------------------------------------------------------------------------------------------------
-
--- Thread to handle the fuel consumption
-function createJerryCanThread()
- CreateThread(function()
- while true do
- Wait(1000)
- local ped = PlayerPedId()
- if not IsPedInAnyVehicle(ped, false) and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH then
- refuelLoop(true)
- end
- end
- end)
-end
-
--- Code to save jerry can ammo in any inventory
-local currentWeaponData
-function updateWeaponAmmo(ammo)
- ammo = math.floor(ammo) -- This is needed or some inventories will break
-
- if currentWeaponData and currentWeaponData.info and currentWeaponData.info.ammo then
- currentWeaponData.info.ammo = ammo
- end
-
- TriggerServerEvent('ox_inventory:updateWeapon', "ammo", ammo)
- TriggerServerEvent("weapons:server:UpdateWeaponAmmo", currentWeaponData, ammo)
- TriggerServerEvent("qb-weapons:server:UpdateWeaponAmmo", currentWeaponData, ammo)
-
- if Config.Debug then print("updateWeaponAmmo:ammo",ammo) end
- if Config.Debug then Utils.Debug.printTable("updateWeaponAmmo:currentWeaponData",currentWeaponData) end
-
- local ped = PlayerPedId()
- SetPedAmmo(ped, JERRY_CAN_HASH, ammo)
-end
-
-AddEventHandler('weapons:client:SetCurrentWeapon', function(data, bool)
- if bool ~= false then
- currentWeaponData = data
- else
- currentWeaponData = {}
- end
-end)
-
-AddEventHandler('qb-weapons:client:SetCurrentWeapon', function(data, bool)
- if bool ~= false then
- currentWeaponData = data
- else
- currentWeaponData = {}
- end
-end)
-
--- Get jerry can ammo by metadata
-function getJerryCanAmmo()
- if currentWeaponData and currentWeaponData.info and currentWeaponData.info.ammo then
- if Config.Debug then print("getJerryCanAmmo:currentWeaponData.info.ammo", currentWeaponData.info.ammo) end
- return currentWeaponData.info.ammo
- end
- local ped = PlayerPedId()
- if Config.Debug then print("getJerryCanAmmo:GetAmmoInPedWeapon", GetAmmoInPedWeapon(ped, JERRY_CAN_HASH)) end
- return GetAmmoInPedWeapon(ped, JERRY_CAN_HASH)
+local customGasPumps = {}
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Threads
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+-- Thread to detect near fuel pumps
+function createGasMarkersThread()
+ CreateThread(function()
+ while true do
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+ local pump, pumpModel = GetClosestPump(playerCoords, false)
+
+ while pump and pump > 0 and #(playerCoords - GetEntityCoords(pump)) < 2.0 do
+ playerCoords = GetEntityCoords(ped)
+ if not mainUiOpen and not DoesEntityExist(fuelNozzle) then
+ Utils.Markers.showHelpNotification(cachedTranslations.open_refuel, true)
+ if IsControlJustPressed(0,38) then
+ clientOpenUI(pump, pumpModel, false)
+ end
+ end
+ Wait(2)
+ end
+ Wait(1000)
+ end
+ end)
+end
+
+function createGasTargetsThread()
+ local pumpModels = {}
+ for _, v in pairs(Config.GasPumpProps) do
+ table.insert(pumpModels, v.prop)
+ end
+ Utils.Target.createTargetForModel(pumpModels,openFuelUICallback,Utils.translate('target.open_refuel'),"fas fa-gas-pump","#a42100",nil,nil,canOpenPumpUiTargetCallback)
+
+ Utils.Target.createTargetForModel(pumpModels,returnNozzle,Utils.translate('target.return_nozzle'),"fas fa-gas-pump","#a42100",nil,nil,canReturnNozzleTargetCallback)
+end
+
+function openFuelUICallback()
+ local ped = PlayerPedId()
+ local playerCoords = GetEntityCoords(ped)
+ local pump, pumpModel = GetClosestPump(playerCoords, false)
+ if pump then
+ clientOpenUI(pump, pumpModel, false)
+ else
+ exports['lc_utils']:notify("error", Utils.translate("pump_not_found"))
+ end
+end
+
+function createCustomPumpModelsThread()
+ for _, pumpConfig in pairs(Config.CustomGasPumpLocations) do
+ RequestModel(pumpConfig.prop)
+
+ while not HasModelLoaded(pumpConfig.prop) do
+ Wait(50)
+ end
+
+ local heading = pumpConfig.location.w + 180.0
+ local gasPump = CreateObject(pumpConfig.prop, pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z, false, true, true)
+ SetEntityHeading(gasPump, heading)
+ FreezeEntityPosition(gasPump, true)
+ table.insert(customGasPumps, gasPump)
+ end
+end
+
+AddEventHandler('onResourceStop', function(resourceName)
+ if GetCurrentResourceName() ~= resourceName then return end
+
+ deleteAllCustomGasPumps()
+end)
+
+function deleteAllCustomGasPumps()
+ for k, v in ipairs(customGasPumps) do
+ DeleteEntity(v)
+ end
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Jerry Cans
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+-- Thread to handle the fuel consumption
+function createJerryCanThread()
+ CreateThread(function()
+ while true do
+ Wait(1000)
+ local ped = PlayerPedId()
+ if not IsPedInAnyVehicle(ped, false) and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH then
+ refuelLoop(true)
+ end
+ end
+ end)
+end
+
+-- Code to save jerry can ammo in any inventory
+local currentWeaponData
+function updateWeaponAmmo(ammo)
+ ammo = math.floor(ammo) -- This is needed or some inventories will break
+
+ if currentWeaponData and currentWeaponData.info and currentWeaponData.info.ammo then
+ currentWeaponData.info.ammo = ammo
+ end
+
+ TriggerServerEvent('ox_inventory:updateWeapon', "ammo", ammo)
+ TriggerServerEvent("weapons:server:UpdateWeaponAmmo", currentWeaponData, ammo)
+ TriggerServerEvent("qb-weapons:server:UpdateWeaponAmmo", currentWeaponData, ammo)
+
+ if Config.Debug then print("updateWeaponAmmo:ammo",ammo) end
+ if Config.Debug then Utils.Debug.printTable("updateWeaponAmmo:currentWeaponData",currentWeaponData) end
+
+ local ped = PlayerPedId()
+ SetPedAmmo(ped, JERRY_CAN_HASH, ammo)
+end
+
+AddEventHandler('weapons:client:SetCurrentWeapon', function(data, bool)
+ if bool ~= false then
+ currentWeaponData = data
+ else
+ currentWeaponData = {}
+ end
+end)
+
+AddEventHandler('qb-weapons:client:SetCurrentWeapon', function(data, bool)
+ if bool ~= false then
+ currentWeaponData = data
+ else
+ currentWeaponData = {}
+ end
+end)
+
+-- Get jerry can ammo by metadata
+function getJerryCanAmmo()
+ if currentWeaponData and currentWeaponData.info and currentWeaponData.info.ammo then
+ if Config.Debug then print("getJerryCanAmmo:currentWeaponData.info.ammo", currentWeaponData.info.ammo) end
+ return currentWeaponData.info.ammo
+ end
+ local ped = PlayerPedId()
+ if Config.Debug then print("getJerryCanAmmo:GetAmmoInPedWeapon", GetAmmoInPedWeapon(ped, JERRY_CAN_HASH)) end
+ return GetAmmoInPedWeapon(ped, JERRY_CAN_HASH)
end
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/client/client_refuel.lua b/resources/[carscripts]/lc_fuel/client/client_refuel.lua
index 0e02abff9..5a1100ce9 100644
--- a/resources/[carscripts]/lc_fuel/client/client_refuel.lua
+++ b/resources/[carscripts]/lc_fuel/client/client_refuel.lua
@@ -1,477 +1,497 @@
-local refuelingThread = nil
-local isRefuelling = false
-local inCooldown = false
-local vehicleAttachedToNozzle = nil
-local remainingFuelToRefuel = 0
-local currentFuelTypePurchased = nil
-local distanceToCap, distanceToPump = math.maxinteger, math.maxinteger
-local litersDeductedEachTick = 0.5
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Refuelling
------------------------------------------------------------------------------------------------------------------------------------------
-
-RegisterNetEvent('lc_fuel:getPumpNozzle')
-AddEventHandler('lc_fuel:getPumpNozzle', function(fuelAmountPurchased, fuelTypePurchased)
- closeUI()
- if DoesEntityExist(fuelNozzle) then return end
- if not currentPump then return end
- local ped = PlayerPedId()
- local pumpCoords = GetEntityCoords(currentPump)
-
- -- Animate the ped to grab the nozzle
- Utils.Animations.loadAnimDict("anim@am_hold_up@male")
- TaskPlayAnim(ped, "anim@am_hold_up@male", "shoplift_high", 2.0, 8.0, -1, 50, 0, false, false, false)
- Wait(300)
- StopAnimTask(ped, "anim@am_hold_up@male", "shoplift_high", 1.0)
-
- -- Spawn the nozzle
- fuelNozzle = createFuelNozzleObject(fuelTypePurchased)
-
- -- Attach the nozzle
- attachNozzleToPed()
- if Config.EnablePumpRope then
- fuelRope = CreateRopeToPump(pumpCoords)
- end
-
- -- Get the max distance the player can go with the nozzle
- local ropeLength = getNearestPumpRopeLength(fuelTypePurchased, pumpCoords)
-
- -- Thread to handle fuel nozzle
- CreateThread(function()
- while DoesEntityExist(fuelNozzle) do
- local waitTime = 500
- local nozzleCoords = GetEntityCoords(fuelNozzle) -- Conside the nozzle position, not the ped
- distanceToPump = #(pumpCoords - nozzleCoords)
- -- If player reach the distance limit delete the nozzle
- if distanceToPump > ropeLength then
- exports['lc_utils']:notify("error", Utils.translate("too_far_away"))
- deleteRopeAndNozzleProp()
- end
- -- If player is near the distance limit, show a notification to him
- if distanceToPump > (ropeLength * 0.7) then
- Utils.Markers.showHelpNotification(Utils.translate("too_far_away"), true)
- end
- -- Check if ped entered a vehicle
- if IsPedSittingInAnyVehicle(ped) then
- -- Gives him 2 seconds to leave before clearing the nozzle
- SetTimeout(2000,function()
- if IsPedSittingInAnyVehicle(ped) and DoesEntityExist(fuelNozzle) then
- exports['lc_utils']:notify("error", Utils.translate("too_far_away"))
- deleteRopeAndNozzleProp()
- end
- end)
- end
- if Utils.Config.custom_scripts_compatibility.target == "disabled" and distanceToPump < 1.5 then
- waitTime = 2
- Utils.Markers.showHelpNotification(cachedTranslations.return_nozzle, true)
- if IsControlJustPressed(0,38) then
- -- See which one the player is nearer. The fuel cap or fuel pump
- if distanceToPump < distanceToCap then
- -- Avoid player press E to return nozzle and press E to refuel in same tick, so it gives preference to refuel
- Wait(100)
- returnNozzle()
- end
- end
- end
- Wait(waitTime)
- end
- -- Not near the pump anymore
- distanceToPump = math.maxinteger
- end)
-
- -- Thread to refuel the vehicle
- CreateThread(function()
- -- Set the fuel purchased in a global variable
- remainingFuelToRefuel = fuelAmountPurchased
- -- Set the fuel type in a global variable
- currentFuelTypePurchased = fuelTypePurchased
- -- Trigger the function to allow refuel on markers
- if Utils.Config.custom_scripts_compatibility.target == "disabled" then
- refuelLoop(false)
- end
- -- Not near the fuel cap anymore
- distanceToCap = math.maxinteger
- end)
-end)
-
-function returnNozzle()
- local ped = PlayerPedId()
-
- if not isRefuelling then
- Utils.Animations.loadAnimDict("anim@am_hold_up@male")
- TaskPlayAnim(ped, "anim@am_hold_up@male", "shoplift_high", 2.0, 8.0, -1, 50, 0, false, false, false)
- Wait(300)
- StopAnimTask(ped, "anim@am_hold_up@male", "shoplift_high", 1.0)
- deleteRopeAndNozzleProp()
-
- if Config.ReturnNozzleRefund then
- local isElectric = Utils.Table.contains({"electricnormal", "electricfast"}, currentFuelTypePurchased)
- TriggerServerEvent('lc_fuel:returnNozzle', remainingFuelToRefuel, isElectric)
- end
- end
-end
-
-function executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
- if Config.Debug then print("executeRefuelAction:p", isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters) end
- local ped = PlayerPedId()
- local refuelTick = Config.RefuelTick
- local isElectric = false
- local fuelTypePurchased = currentFuelTypePurchased
-
- -- Change the fuel tick if its electric charging
- if fuelTypePurchased == "electricfast" then
- isElectric = true
- refuelTick = Config.Electric.chargeTypes.fast.time * 1000 / 2 -- Divide by 2 because each tick adds 0.5kWh.
- end
- if fuelTypePurchased == "electricnormal" then
- isElectric = true
- refuelTick = Config.Electric.chargeTypes.normal.time * 1000 / 2
- end
-
- local animationDuration = 1000 -- 1 sec
- if isFromJerryCan then
- animationDuration = -1 -- (infinite) Do not allow the player walk during refuel from jerry can
- end
-
- -- Do not allow user mix electric and petrol fuel/vehicles
- if (isElectric and Config.Electric.vehiclesListHash[closestVehicleHash]) or (not isElectric and not Config.Electric.vehiclesListHash[closestVehicleHash]) then
- if not isRefuelling and not vehicleAttachedToNozzle then
- if remainingFuelToRefuel > 0 then
- -- Reset the vehicle fuel to 0 when refueling with a different fuel type
- if not isFromJerryCan and not isElectric then
- local fuelType = getVehicleFuelTypeFromServer(closestVehicle)
- if fuelTypePurchased ~= fuelType then
- changeVehicleFuelType(closestVehicle, fuelTypePurchased)
- end
- end
- isRefuelling = true
-
- -- Animate the ped
- TaskTurnPedToFaceCoord(ped, closestCapPos.x, closestCapPos.y, closestCapPos.z, animationDuration)
- Utils.Animations.loadAnimDict("weapons@misc@jerrycan@")
- TaskPlayAnim(ped, "weapons@misc@jerrycan@", "fire", 2.0, 8.0, animationDuration, 50, 0, false, false, false)
-
- -- Plug the nozzle in the car
- attachNozzleToVehicle(closestVehicle, customVehicleParameters)
-
- -- Refuel the vehicle
- refuelingThread = CreateThread(function()
- local vehicleToRefuel = closestVehicle
- local startingFuel = GetFuel(vehicleToRefuel) -- Get vehicle fuel level
- local vehicleTankSize = getVehicleTankSize(vehicleToRefuel)
-
- local currentFuel = startingFuel
- -- Loop keep happening while the player has not canceled, while the fuelNozzle exists and while the ped still has jerry can in hands
- while isRefuelling and (DoesEntityExist(fuelNozzle) or (isFromJerryCan and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)) do
- currentFuel = GetFuel(vehicleToRefuel)
- local percentageOfFuelToAdd = calculateFuelToAddPercentage(vehicleTankSize) -- Add 0.5L each tick, but the % is proportional to the vehicle tank
- if currentFuel + percentageOfFuelToAdd > 100 then
- -- Increase the vehicle fuel level
- percentageOfFuelToAdd = 100 - currentFuel
- end
- if remainingFuelToRefuel < litersDeductedEachTick then
- -- Break when the user has used all the fuel he paid for
- break
- end
- if percentageOfFuelToAdd <= 0.01 then
- -- Break when the vehicle tank is full
- exports['lc_utils']:notify("info", Utils.translate("vehicle_tank_full"))
- break
- end
- -- Decrease the purchased fuel amount and increase the vehicle fuel level
- remainingFuelToRefuel = remainingFuelToRefuel - litersDeductedEachTick
- currentFuel = currentFuel + percentageOfFuelToAdd
- SetFuel(vehicleToRefuel, currentFuel)
- SendNUIMessage({
- showRefuelDisplay = true,
- remainingFuelAmount = remainingFuelToRefuel,
- currentVehicleTankSize = vehicleTankSize,
- currentDisplayFuelAmount = getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize),
- isElectric = isElectric,
- fuelTypePurchased = fuelTypePurchased
- })
- if Config.Debug then print("executeRefuelAction:remainingFuelToRefuel", remainingFuelToRefuel) end
- Wait(refuelTick)
- end
- if isFromJerryCan then
- -- Update the jerry can ammo
- SetPedAmmo(ped, JERRY_CAN_HASH, remainingFuelToRefuel)
- updateWeaponAmmo(remainingFuelToRefuel)
- vehicleAttachedToNozzle = nil
- end
- if isElectric then
- exports['lc_utils']:notify("success", Utils.translate("vehicle_recharged"):format(Utils.Math.round(getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize) - getVehicleDisplayFuelAmount(startingFuel, vehicleTankSize), 1)))
- else
- exports['lc_utils']:notify("success", Utils.translate("vehicle_refueled"):format(Utils.Math.round(getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize) - getVehicleDisplayFuelAmount(startingFuel, vehicleTankSize), 1)))
- end
-
- -- Stop refuelling
- stopRefuelAnimation()
- SendNUIMessage({ hideRefuelDisplay = true })
- isRefuelling = false
- end)
- else
- exports['lc_utils']:notify("error", Utils.translate("not_enough_refuel"))
- end
- else
- -- Terminate refuelling
- stopRefuelAction()
- -- Cooldown to prevent the user to spam E and glitch things
- inCooldown = true
- SetTimeout(refuelTick + 1,function()
- inCooldown = false
- end)
- end
- else
- exports['lc_utils']:notify("error", Utils.translate("incompatible_fuel"))
- end
-end
-
-function calculateFuelToAddPercentage(totalVolumeLiters)
- local percentage = (litersDeductedEachTick / totalVolumeLiters) * 100
- return percentage
-end
-
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Markers
------------------------------------------------------------------------------------------------------------------------------------------
-
-function refuelLoop(isFromJerryCan)
- -- Load variables to open te UI
- loadNuiVariables()
-
- local ped = PlayerPedId()
- local closestCapPos
- local closestVehicle
- local customVehicleParameters
- local closestVehicleHash
-
- if isFromJerryCan then
- remainingFuelToRefuel = getJerryCanAmmo()
- end
-
- isRefuelling = false
- while DoesEntityExist(fuelNozzle) or (isFromJerryCan and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH) do
- local waitTime = 200
- if closestCapPos then
- distanceToCap = #(GetEntityCoords(ped) - vector3(closestCapPos.x,closestCapPos.y,closestCapPos.z + customVehicleParameters.nozzleOffset.up + 0.0))
- if distanceToCap < customVehicleParameters.distance + 0.0 and (not vehicleAttachedToNozzle or (vehicleAttachedToNozzle and DoesEntityExist(vehicleAttachedToNozzle) and vehicleAttachedToNozzle == closestVehicle)) then
- waitTime = 1
- Utils.Markers.drawText3D(closestCapPos.x,closestCapPos.y,closestCapPos.z + customVehicleParameters.nozzleOffset.up + 0.0, cachedTranslations.interact_with_vehicle)
- if IsControlJustPressed(0, 38) and not inCooldown then
- -- See which one the player is nearer. The fuel cap or fuel pump
- if distanceToPump >= distanceToCap then
- executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
- end
- end
- else
- -- Player is not near the cap, set it to null to find it again later
- closestCapPos = nil
- end
- else
- -- Find the nearest vehicle and cap pos
- closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters = getClosestVehicleVariables()
- end
- Wait(waitTime)
- end
-
- terminateRefuelThread()
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Target
------------------------------------------------------------------------------------------------------------------------------------------
-
-function createTargetForVehicleIteraction()
- local attachParams = {
- labelText = Utils.translate("target.start_refuel"),
- icon = "fas fa-gas-pump",
- iconColor = "#2986cc",
- zone_id = "start_refuel",
- distance = 2.0
- }
-
- Utils.Target.createTargetForBone(vehicleCapBoneList(),attachParams,executeRefuelActionFromTarget,nil,canAttachNozzleTargetCallback)
-
- local detachParams = {
- labelText = Utils.translate("target.stop_refuel"),
- icon = "fas fa-gas-pump",
- iconColor = "#2986cc",
- zone_id = "stop_refuel",
- distance = 2.0
- }
- Utils.Target.createTargetForBone(vehicleCapBoneList(),detachParams,stopRefuelAction,nil,canDetachNozzleTargetCallback)
-end
-
-function executeRefuelActionFromTarget()
- -- Load variables to open te UI
- loadNuiVariables()
-
- local ped = PlayerPedId()
-
- -- Calculate if player is holding a jerry can
- local isFromJerryCan = false
- if not IsPedInAnyVehicle(ped, false) and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH then
- isFromJerryCan = true
- remainingFuelToRefuel = getJerryCanAmmo()
- if Config.Debug then print("executeRefuelActionFromTarget:remainingFuelToRefuel",remainingFuelToRefuel) end
- end
-
- local closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters = getClosestVehicleVariables()
- executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
-end
-
-function canAttachNozzleTargetCallback(entity, distance)
- local ped = PlayerPedId()
- if (DoesEntityExist(fuelNozzle) or GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)
- and not isRefuelling
- and not vehicleAttachedToNozzle then
- return true
- end
- return false
-end
-
-function canDetachNozzleTargetCallback(entity, distance)
- local ped = PlayerPedId()
- if (DoesEntityExist(fuelNozzle) or GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)
- and vehicleAttachedToNozzle then
- return true
- end
- return false
-end
-
-function canOpenPumpUiTargetCallback()
- return not DoesEntityExist(fuelNozzle)
-end
-
-function canReturnNozzleTargetCallback()
- return DoesEntityExist(fuelNozzle)
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Utils
------------------------------------------------------------------------------------------------------------------------------------------
-
-function getClosestVehicleVariables()
- -- Get the closest vehicle and its cap pos
- local closestVehicle = GetClosestVehicle()
- local closestCapPos = GetVehicleCapPos(closestVehicle)
- local closestVehicleHash = GetEntityModel(closestVehicle)
- local customVehicleParameters = (Config.CustomVehicleParametersHash[closestVehicleHash] or Config.CustomVehicleParametersHash.default or { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.15, up = 0.5 }, nozzleRotation = { x = 0, y = 0, z = 0} })
- if not closestCapPos then
- print("Cap not found for vehicle")
- end
- return closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters
-end
-
-function terminateRefuelThread()
- -- Stop the refueling process
- if refuelingThread and IsThreadActive(refuelingThread) then
- TerminateThread(refuelingThread)
- refuelingThread = nil
- end
-end
-
-function stopRefuelAnimation()
- local ped = PlayerPedId()
- ClearPedTasks(ped)
- RemoveAnimDict("weapons@misc@jerrycan@")
-end
-
-function stopRefuelAction()
- -- Stop refuelling
- stopRefuelAnimation()
- SendNUIMessage({ hideRefuelDisplay = true })
- attachNozzleToPed()
- isRefuelling = false
-end
-
-function attachNozzleToVehicle(closestVehicle, customVehicleParameters)
- DetachEntity(fuelNozzle, true, true)
-
- -- Find the appropriate bone for the fuel cap
- local tankBones = vehicleCapBoneList()
- local boneIndex = -1
-
- for _, boneName in ipairs(tankBones) do
- boneIndex = GetEntityBoneIndexByName(closestVehicle, boneName)
- if boneIndex ~= -1 then
- break
- end
- end
-
- if boneIndex ~= -1 then
- local vehicleRotation = GetEntityRotation(closestVehicle)
- local forwardVector, rightVector, upVector, _ = GetEntityMatrix(closestVehicle)
-
- -- Adjust the offsets
- local forwardOffset = forwardVector * customVehicleParameters.nozzleOffset.forward
- local rightoffset = rightVector * customVehicleParameters.nozzleOffset.right
- local upOffset = upVector * customVehicleParameters.nozzleOffset.up
- local finalOffset = forwardOffset + rightoffset + upOffset
-
- -- Adjust the rotation
- local nozzleRotation = customVehicleParameters.nozzleRotation or { x = 0, y = 0, z = 0 }
- local finalRotationX = vehicleRotation.x + nozzleRotation.x
- local finalRotationY = vehicleRotation.y + nozzleRotation.y
- local finalRotationZ = vehicleRotation.z + nozzleRotation.z
-
- -- Attach the nozzle to the vehicle's fuel cap bone with the calculated rotation
- AttachEntityToEntity(fuelNozzle, closestVehicle, boneIndex, finalOffset.x, finalOffset.y, finalOffset.z, finalRotationX - 45, finalRotationY, finalRotationZ - 90, false, false, false, false, 2, false)
- else
- print("No valid fuel cap bone found on the vehicle.")
- end
-
- -- Set the global variable to indicate the vehicle attached to nozzle
- vehicleAttachedToNozzle = closestVehicle
-end
-
-function attachNozzleToPed()
- DetachEntity(fuelNozzle, true, true)
-
- local ped = PlayerPedId()
- local pedBone = GetPedBoneIndex(ped, 18905)
- AttachEntityToEntity(fuelNozzle, ped, pedBone, 0.13, 0.04, 0.01, -42.0, -115.0, -63.42, false, true, false, true, 0, true)
-
- vehicleAttachedToNozzle = nil
-end
-
-function getNearestPumpRopeLength(fuelTypePurchased, pumpCoords)
- local distanceToFindPump = 10
- local ropeLength = Config.DefaultRopeLength
- if fuelTypePurchased == "electricfast" or fuelTypePurchased == "electricnormal" then
- for _, pumpConfig in pairs(Config.Electric.chargersLocation) do
- local distance = #(vector3(pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z) - pumpCoords)
- if distance < distanceToFindPump then
- ropeLength = pumpConfig.ropeLength
- break
- end
- end
- else
- for _, pumpConfig in pairs(Config.CustomGasPumpLocations) do
- local distance = #(vector3(pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z) - pumpCoords)
- if distance < distanceToFindPump then
- ropeLength = pumpConfig.ropeLength
- break
- end
- end
- end
- return ropeLength
-end
-
-function createFuelNozzleObject(fuelTypePurchased)
- local nozzle_prop_label = Config.NozzleProps.gas
- -- Change the nozzle prop to electric
- if fuelTypePurchased == "electricfast" or fuelTypePurchased == "electricnormal" then
- nozzle_prop_label = Config.NozzleProps.electric
- end
-
- RequestModel(nozzle_prop_label)
- while not HasModelLoaded(nozzle_prop_label) do
- Wait(50)
- end
-
- return CreateObject(joaat(nozzle_prop_label), 1.0, 1.0, 1.0, true, true, false)
+local refuelingThread = nil
+local isRefuelling = false
+local inCooldown = false
+local vehicleAttachedToNozzle = nil
+local remainingFuelToRefuel = 0
+local currentFuelTypePurchased = nil
+local distanceToCap, distanceToPump = math.maxinteger, math.maxinteger
+local litersDeductedEachTick = 0.5
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Refuelling
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+RegisterNetEvent('lc_fuel:getPumpNozzle')
+AddEventHandler('lc_fuel:getPumpNozzle', function(fuelAmountPurchased, fuelTypePurchased)
+ closeUI()
+ if DoesEntityExist(fuelNozzle) then return end
+ if not currentPump then return end
+ local ped = PlayerPedId()
+ local pumpCoords = GetEntityCoords(currentPump)
+
+ -- Animate the ped to grab the nozzle
+ Utils.Animations.loadAnimDict("anim@am_hold_up@male")
+ TaskPlayAnim(ped, "anim@am_hold_up@male", "shoplift_high", 2.0, 8.0, -1, 50, 0, false, false, false)
+ Wait(300)
+ StopAnimTask(ped, "anim@am_hold_up@male", "shoplift_high", 1.0)
+
+ -- Spawn the nozzle
+ fuelNozzle = createFuelNozzleObject(fuelTypePurchased)
+
+ -- Attach the nozzle
+ attachNozzleToPed()
+ if Config.EnablePumpRope then
+ fuelRope = CreateRopeToPump(pumpCoords)
+ end
+
+ -- Get the max distance the player can go with the nozzle
+ local ropeLength = getNearestPumpRopeLength(fuelTypePurchased, pumpCoords)
+
+ -- Thread to handle fuel nozzle
+ CreateThread(function()
+ while DoesEntityExist(fuelNozzle) do
+ local waitTime = 500
+ local nozzleCoords = GetEntityCoords(fuelNozzle) -- Conside the nozzle position, not the ped
+ distanceToPump = #(pumpCoords - nozzleCoords)
+ -- If player reach the distance limit delete the nozzle
+ if distanceToPump > ropeLength then
+ exports['lc_utils']:notify("error", Utils.translate("too_far_away"))
+ deleteRopeAndNozzleProp()
+ end
+ -- If player is near the distance limit, show a notification to him
+ if distanceToPump > (ropeLength * 0.7) then
+ Utils.Markers.showHelpNotification(Utils.translate("too_far_away"), true)
+ end
+ -- Check if ped entered a vehicle
+ if IsPedSittingInAnyVehicle(ped) then
+ -- Gives him 2 seconds to leave before clearing the nozzle
+ SetTimeout(2000,function()
+ if IsPedSittingInAnyVehicle(ped) and DoesEntityExist(fuelNozzle) then
+ exports['lc_utils']:notify("error", Utils.translate("too_far_away"))
+ deleteRopeAndNozzleProp()
+ end
+ end)
+ end
+ if Utils.Config.custom_scripts_compatibility.target == "disabled" and distanceToPump < 1.5 then
+ waitTime = 2
+ Utils.Markers.showHelpNotification(cachedTranslations.return_nozzle, true)
+ if IsControlJustPressed(0,38) then
+ -- See which one the player is nearer. The fuel cap or fuel pump
+ if distanceToPump < distanceToCap then
+ -- Avoid player press E to return nozzle and press E to refuel in same tick, so it gives preference to refuel
+ Wait(100)
+ returnNozzle()
+ end
+ end
+ end
+ Wait(waitTime)
+ end
+ -- Not near the pump anymore
+ distanceToPump = math.maxinteger
+ end)
+
+ -- Thread to refuel the vehicle
+ CreateThread(function()
+ -- Set the fuel purchased in a global variable
+ remainingFuelToRefuel = fuelAmountPurchased
+ -- Set the fuel type in a global variable
+ currentFuelTypePurchased = fuelTypePurchased
+ -- Trigger the function to allow refuel on markers
+ if Utils.Config.custom_scripts_compatibility.target == "disabled" then
+ refuelLoop(false)
+ end
+ -- Not near the fuel cap anymore
+ distanceToCap = math.maxinteger
+ end)
+end)
+
+function returnNozzle()
+ local ped = PlayerPedId()
+
+ if not isRefuelling then
+ Utils.Animations.loadAnimDict("anim@am_hold_up@male")
+ TaskPlayAnim(ped, "anim@am_hold_up@male", "shoplift_high", 2.0, 8.0, -1, 50, 0, false, false, false)
+ Wait(300)
+ StopAnimTask(ped, "anim@am_hold_up@male", "shoplift_high", 1.0)
+ deleteRopeAndNozzleProp()
+
+ if Config.ReturnNozzleRefund then
+ local isElectric = Utils.Table.contains({"electricnormal", "electricfast"}, currentFuelTypePurchased)
+ TriggerServerEvent('lc_fuel:returnNozzle', remainingFuelToRefuel, isElectric)
+ end
+ end
+end
+
+function executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
+ if Config.Debug then print("executeRefuelAction:p", isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters) end
+ local ped = PlayerPedId()
+ local refuelTick = Config.RefuelTick
+ local isElectric = false
+ local fuelTypePurchased = currentFuelTypePurchased
+
+ -- Change the fuel tick if its electric charging
+ if fuelTypePurchased == "electricfast" then
+ isElectric = true
+ refuelTick = Config.Electric.chargeTypes.fast.time * 1000 / 2 -- Divide by 2 because each tick adds 0.5kWh.
+ end
+ if fuelTypePurchased == "electricnormal" then
+ isElectric = true
+ refuelTick = Config.Electric.chargeTypes.normal.time * 1000 / 2
+ end
+
+ local animationDuration = 1000 -- 1 sec
+ if isFromJerryCan then
+ animationDuration = -1 -- (infinite) Do not allow the player walk during refuel from jerry can
+ end
+
+ -- Do not allow user mix electric and petrol fuel/vehicles
+ if (isElectric and Config.Electric.vehiclesListHash[closestVehicleHash]) or (not isElectric and not Config.Electric.vehiclesListHash[closestVehicleHash]) then
+ if not isRefuelling and not vehicleAttachedToNozzle then
+ if remainingFuelToRefuel > 0 then
+ -- Reset the vehicle fuel to 0 when refueling with a different fuel type
+ if not isFromJerryCan and not isElectric then
+ local fuelType = getVehicleFuelTypeFromServer(closestVehicle)
+ if fuelTypePurchased ~= fuelType then
+ changeVehicleFuelType(closestVehicle, fuelTypePurchased)
+ end
+ end
+ isRefuelling = true
+
+ -- Animate the ped
+ TaskTurnPedToFaceCoord(ped, closestCapPos.x, closestCapPos.y, closestCapPos.z, animationDuration)
+ Utils.Animations.loadAnimDict("weapons@misc@jerrycan@")
+ TaskPlayAnim(ped, "weapons@misc@jerrycan@", "fire", 2.0, 8.0, animationDuration, 50, 0, false, false, false)
+
+ -- Plug the nozzle in the car
+ attachNozzleToVehicle(closestVehicle, customVehicleParameters)
+
+ -- Refuel the vehicle
+ refuelingThread = CreateThread(function()
+ local vehicleToRefuel = closestVehicle
+ local startingFuel = GetFuel(vehicleToRefuel) -- Get vehicle fuel level
+ local vehicleTankSize = getVehicleTankSize(vehicleToRefuel)
+
+ local currentFuel = startingFuel
+ -- Loop keep happening while the player has not canceled, while the fuelNozzle exists and while the ped still has jerry can in hands
+ while isRefuelling and (DoesEntityExist(fuelNozzle) or (isFromJerryCan and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)) do
+ currentFuel = GetFuel(vehicleToRefuel)
+ local percentageOfFuelToAdd = calculateFuelToAddPercentage(vehicleTankSize) -- Add 0.5L each tick, but the % is proportional to the vehicle tank
+ if currentFuel + percentageOfFuelToAdd > 100 then
+ -- Increase the vehicle fuel level
+ percentageOfFuelToAdd = 100 - currentFuel
+ end
+ if remainingFuelToRefuel < litersDeductedEachTick then
+ -- Break when the user has used all the fuel he paid for
+ break
+ end
+ if percentageOfFuelToAdd <= 0.01 then
+ -- Break when the vehicle tank is full
+ exports['lc_utils']:notify("info", Utils.translate("vehicle_tank_full"))
+ break
+ end
+ -- Decrease the purchased fuel amount and increase the vehicle fuel level
+ remainingFuelToRefuel = remainingFuelToRefuel - litersDeductedEachTick
+ currentFuel = currentFuel + percentageOfFuelToAdd
+ SetFuel(vehicleToRefuel, currentFuel)
+ SendNUIMessage({
+ showRefuelDisplay = true,
+ remainingFuelAmount = remainingFuelToRefuel,
+ currentVehicleTankSize = vehicleTankSize,
+ currentDisplayFuelAmount = getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize),
+ isElectric = isElectric,
+ fuelTypePurchased = fuelTypePurchased
+ })
+ if Config.Debug then print("executeRefuelAction:remainingFuelToRefuel", remainingFuelToRefuel) end
+ Wait(refuelTick)
+ end
+ if isFromJerryCan then
+ -- Update the jerry can ammo
+ SetPedAmmo(ped, JERRY_CAN_HASH, remainingFuelToRefuel)
+ updateWeaponAmmo(remainingFuelToRefuel)
+ vehicleAttachedToNozzle = nil
+ end
+ if isElectric then
+ exports['lc_utils']:notify("success", Utils.translate("vehicle_recharged"):format(Utils.Math.round(getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize) - getVehicleDisplayFuelAmount(startingFuel, vehicleTankSize), 1)))
+ else
+ exports['lc_utils']:notify("success", Utils.translate("vehicle_refueled"):format(Utils.Math.round(getVehicleDisplayFuelAmount(currentFuel, vehicleTankSize) - getVehicleDisplayFuelAmount(startingFuel, vehicleTankSize), 1)))
+ end
+
+ -- Stop refuelling
+ stopRefuelAnimation()
+ SendNUIMessage({ hideRefuelDisplay = true })
+ isRefuelling = false
+ end)
+ else
+ exports['lc_utils']:notify("error", Utils.translate("not_enough_refuel"))
+ end
+ else
+ -- Terminate refuelling
+ stopRefuelAction()
+ -- Cooldown to prevent the user to spam E and glitch things
+ inCooldown = true
+ SetTimeout(refuelTick + 1,function()
+ inCooldown = false
+ end)
+ end
+ else
+ exports['lc_utils']:notify("error", Utils.translate("incompatible_fuel"))
+ end
+end
+
+function calculateFuelToAddPercentage(totalVolumeLiters)
+ local percentage = (litersDeductedEachTick / totalVolumeLiters) * 100
+ return percentage
+end
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Markers
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function refuelLoop(isFromJerryCan)
+ -- Load variables to open te UI
+ loadNuiVariables()
+
+ local ped = PlayerPedId()
+ local closestCapPos
+ local closestVehicle
+ local customVehicleParameters
+ local closestVehicleHash
+
+ if isFromJerryCan then
+ remainingFuelToRefuel = getJerryCanAmmo()
+ end
+
+ isRefuelling = false
+ while DoesEntityExist(fuelNozzle) or (isFromJerryCan and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH) do
+ local waitTime = 200
+ if closestCapPos then
+ distanceToCap = #(GetEntityCoords(ped) - vector3(closestCapPos.x,closestCapPos.y,closestCapPos.z))
+ if distanceToCap < customVehicleParameters.distance + 0.0 and (not vehicleAttachedToNozzle or (vehicleAttachedToNozzle and DoesEntityExist(vehicleAttachedToNozzle) and vehicleAttachedToNozzle == closestVehicle)) then
+ waitTime = 1
+ Utils.Markers.drawText3D(closestCapPos.x,closestCapPos.y,closestCapPos.z, cachedTranslations.interact_with_vehicle)
+ if IsControlJustPressed(0, 38) and not inCooldown then
+ -- See which one the player is nearer. The fuel cap or fuel pump
+ if distanceToPump >= distanceToCap then
+ executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
+ end
+ end
+ else
+ -- Player is not near the cap, set it to null to find it again later
+ closestCapPos = nil
+ end
+ else
+ -- Find the nearest vehicle and cap pos
+ closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters = getClosestVehicleVariables()
+ end
+ Wait(waitTime)
+ end
+
+ terminateRefuelThread()
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Target
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function createTargetForVehicleIteraction()
+ local attachParams = {
+ labelText = Utils.translate("target.start_refuel"),
+ icon = "fas fa-gas-pump",
+ iconColor = "#2986cc",
+ zone_id = "start_refuel",
+ distance = 2.0
+ }
+
+ Utils.Target.createTargetForBone(vehicleCapBoneList(),attachParams,executeRefuelActionFromTarget,nil,canAttachNozzleTargetCallback)
+
+ local detachParams = {
+ labelText = Utils.translate("target.stop_refuel"),
+ icon = "fas fa-gas-pump",
+ iconColor = "#2986cc",
+ zone_id = "stop_refuel",
+ distance = 2.0
+ }
+ Utils.Target.createTargetForBone(vehicleCapBoneList(),detachParams,stopRefuelAction,nil,canDetachNozzleTargetCallback)
+end
+
+function executeRefuelActionFromTarget()
+ -- Load variables to open te UI
+ loadNuiVariables()
+
+ local ped = PlayerPedId()
+
+ -- Calculate if player is holding a jerry can
+ local isFromJerryCan = false
+ if not IsPedInAnyVehicle(ped, false) and GetSelectedPedWeapon(ped) == JERRY_CAN_HASH then
+ isFromJerryCan = true
+ remainingFuelToRefuel = getJerryCanAmmo()
+ if Config.Debug then print("executeRefuelActionFromTarget:remainingFuelToRefuel",remainingFuelToRefuel) end
+ end
+
+ local closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters = getClosestVehicleVariables()
+ executeRefuelAction(isFromJerryCan, closestVehicle, closestCapPos, closestVehicleHash, customVehicleParameters)
+end
+
+function canAttachNozzleTargetCallback(entity, distance)
+ local ped = PlayerPedId()
+ if (DoesEntityExist(fuelNozzle) or GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)
+ and not isRefuelling
+ and not vehicleAttachedToNozzle then
+ return true
+ end
+ return false
+end
+
+function canDetachNozzleTargetCallback(entity, distance)
+ local ped = PlayerPedId()
+ if (DoesEntityExist(fuelNozzle) or GetSelectedPedWeapon(ped) == JERRY_CAN_HASH)
+ and vehicleAttachedToNozzle then
+ return true
+ end
+ return false
+end
+
+function canOpenPumpUiTargetCallback()
+ return not DoesEntityExist(fuelNozzle)
+end
+
+function canReturnNozzleTargetCallback()
+ return DoesEntityExist(fuelNozzle)
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Utils
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function getClosestVehicleVariables()
+ -- Get the closest vehicle and its cap pos
+ local closestVehicle = GetClosestVehicle()
+ local closestCapPos = GetVehicleCapPos(closestVehicle)
+ local closestVehicleHash = GetEntityModel(closestVehicle)
+ local customVehicleParameters = (Config.CustomVehicleParametersHash[closestVehicleHash] or Config.CustomVehicleParametersHash.default or { distance = 1.2, nozzleOffset = { forward = 0.0, right = -0.15, up = 0.5 }, nozzleRotation = { x = 0, y = 0, z = 0} })
+ if not closestCapPos then
+ print("Cap not found for vehicle")
+ end
+
+ local finalWorldPos = getWorldPosFromOffset(closestVehicle, customVehicleParameters.nozzleOffset)
+
+ return closestVehicle, finalWorldPos, closestVehicleHash, customVehicleParameters
+end
+
+function getWorldPosFromOffset(vehicle, offset)
+ local closestCapPos = GetVehicleCapPos(vehicle)
+ local forwardVector, rightVector, upVector, _ = GetEntityMatrix(vehicle)
+
+ -- Adjust the offsets
+ local forwardOffset = forwardVector * offset.forward
+ local rightoffset = rightVector * offset.right
+ local upOffset = upVector * offset.up
+
+ -- Final world position of the nozzle point
+ return vector3(
+ closestCapPos.x + forwardOffset.x + rightoffset.x + upOffset.x,
+ closestCapPos.y + forwardOffset.y + rightoffset.y + upOffset.y,
+ closestCapPos.z + forwardOffset.z + rightoffset.z + upOffset.z
+ )
+end
+
+function terminateRefuelThread()
+ -- Stop the refueling process
+ if refuelingThread and IsThreadActive(refuelingThread) then
+ TerminateThread(refuelingThread)
+ refuelingThread = nil
+ end
+end
+
+function stopRefuelAnimation()
+ local ped = PlayerPedId()
+ ClearPedTasks(ped)
+ RemoveAnimDict("weapons@misc@jerrycan@")
+end
+
+function stopRefuelAction()
+ -- Stop refuelling
+ stopRefuelAnimation()
+ SendNUIMessage({ hideRefuelDisplay = true })
+ attachNozzleToPed()
+ isRefuelling = false
+end
+
+function attachNozzleToVehicle(closestVehicle, customVehicleParameters)
+ DetachEntity(fuelNozzle, true, true)
+
+ -- Find the appropriate bone for the fuel cap
+ local tankBones = vehicleCapBoneList()
+ local boneIndex = -1
+
+ for _, boneName in ipairs(tankBones) do
+ boneIndex = GetEntityBoneIndexByName(closestVehicle, boneName)
+ if boneIndex ~= -1 then
+ break
+ end
+ end
+
+ if boneIndex ~= -1 then
+ local vehicleRotation = GetEntityRotation(closestVehicle)
+ local forwardVector, rightVector, upVector, _ = GetEntityMatrix(closestVehicle)
+
+ -- Adjust the offsets
+ local forwardOffset = forwardVector * customVehicleParameters.nozzleOffset.forward
+ local rightoffset = rightVector * customVehicleParameters.nozzleOffset.right
+ local upOffset = upVector * customVehicleParameters.nozzleOffset.up
+ local finalOffset = forwardOffset + rightoffset + upOffset
+
+ -- Adjust the rotation
+ local nozzleRotation = customVehicleParameters.nozzleRotation or { x = 0, y = 0, z = 0 }
+ local finalRotationX = vehicleRotation.x + nozzleRotation.x
+ local finalRotationY = vehicleRotation.y + nozzleRotation.y
+ local finalRotationZ = vehicleRotation.z + nozzleRotation.z
+
+ -- Attach the nozzle to the vehicle's fuel cap bone with the calculated rotation
+ AttachEntityToEntity(fuelNozzle, closestVehicle, boneIndex, finalOffset.x, finalOffset.y, finalOffset.z, finalRotationX - 45, finalRotationY, finalRotationZ - 90, false, false, false, false, 2, false)
+ else
+ print("No valid fuel cap bone found on the vehicle.")
+ end
+
+ -- Set the global variable to indicate the vehicle attached to nozzle
+ vehicleAttachedToNozzle = closestVehicle
+end
+
+function attachNozzleToPed()
+ DetachEntity(fuelNozzle, true, true)
+
+ local ped = PlayerPedId()
+ local pedBone = GetPedBoneIndex(ped, 18905)
+ AttachEntityToEntity(fuelNozzle, ped, pedBone, 0.13, 0.04, 0.01, -42.0, -115.0, -63.42, false, true, false, true, 0, true)
+
+ vehicleAttachedToNozzle = nil
+end
+
+function getNearestPumpRopeLength(fuelTypePurchased, pumpCoords)
+ local distanceToFindPump = 10
+ local ropeLength = Config.DefaultRopeLength
+ if fuelTypePurchased == "electricfast" or fuelTypePurchased == "electricnormal" then
+ for _, pumpConfig in pairs(Config.Electric.chargersLocation) do
+ local distance = #(vector3(pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z) - pumpCoords)
+ if distance < distanceToFindPump then
+ ropeLength = pumpConfig.ropeLength
+ break
+ end
+ end
+ else
+ for _, pumpConfig in pairs(Config.CustomGasPumpLocations) do
+ local distance = #(vector3(pumpConfig.location.x, pumpConfig.location.y, pumpConfig.location.z) - pumpCoords)
+ if distance < distanceToFindPump then
+ ropeLength = pumpConfig.ropeLength
+ break
+ end
+ end
+ end
+ return ropeLength
+end
+
+function createFuelNozzleObject(fuelTypePurchased)
+ local nozzle_prop_label = Config.NozzleProps.gas
+ -- Change the nozzle prop to electric
+ if fuelTypePurchased == "electricfast" or fuelTypePurchased == "electricnormal" then
+ nozzle_prop_label = Config.NozzleProps.electric
+ end
+
+ RequestModel(nozzle_prop_label)
+ while not HasModelLoaded(nozzle_prop_label) do
+ Wait(50)
+ end
+
+ return CreateObject(joaat(nozzle_prop_label), 1.0, 1.0, 1.0, true, true, false)
end
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/fxmanifest.lua b/resources/[carscripts]/lc_fuel/fxmanifest.lua
index 2e8c226f5..9c60e8458 100644
--- a/resources/[carscripts]/lc_fuel/fxmanifest.lua
+++ b/resources/[carscripts]/lc_fuel/fxmanifest.lua
@@ -1,48 +1,49 @@
-fx_version 'cerulean'
-game 'gta5'
-author 'LixeiroCharmoso'
-name 'lc_fuel'
-
-ui_page "nui/ui.html"
-
-lua54 'yes'
-
-escrow_ignore {
- '**'
-}
-
-client_scripts {
- "client/client.lua",
- "client/client_gas.lua",
- "client/client_electric.lua",
- "client/client_refuel.lua",
- "client/client_fuel_chart.lua",
-}
-
-server_scripts {
- "@mysql-async/lib/MySQL.lua",
- "server/server.lua",
-}
-
-shared_scripts {
- "lang/*.lua",
- "config.lua",
- "@lc_utils/functions/loader.lua",
-}
-
-files {
- "version",
- "nui/lang/*",
- "nui/ui.html",
- "nui/panel.js",
- "nui/scripts/*",
- "nui/css/*",
- "nui/images/*",
- "nui/fonts/Technology.woff",
-}
-
-dependency "lc_utils"
-provides 'LegacyFuel'
-
-data_file 'DLC_ITYP_REQUEST' 'stream/prop_electric_01.ytyp'
+fx_version 'cerulean'
+game 'gta5'
+author 'LixeiroCharmoso'
+name 'lc_fuel'
+
+ui_page "nui/ui.html"
+
+lua54 'yes'
+
+escrow_ignore {
+ '**'
+}
+
+client_scripts {
+ "client/client.lua",
+ "client/client_gas.lua",
+ "client/client_electric.lua",
+ "client/client_refuel.lua",
+ "client/client_fuel_chart.lua",
+ "client/client_fuel_type.lua",
+}
+
+server_scripts {
+ "@mysql-async/lib/MySQL.lua",
+ "server/server.lua",
+}
+
+shared_scripts {
+ "lang/*.lua",
+ "config.lua",
+ "@lc_utils/functions/loader.lua",
+}
+
+files {
+ "version",
+ "nui/lang/*",
+ "nui/ui.html",
+ "nui/panel.js",
+ "nui/scripts/*",
+ "nui/css/*",
+ "nui/images/*",
+ "nui/fonts/Technology.woff",
+}
+
+dependency "lc_utils"
+provides 'LegacyFuel'
+
+data_file 'DLC_ITYP_REQUEST' 'stream/prop_electric_01.ytyp'
data_file 'DLC_ITYP_REQUEST' 'stream/prop_eletricpistol.ytyp'
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/lang/de.lua b/resources/[carscripts]/lc_fuel/lang/de.lua
index 3786d0991..f7b3a6a4c 100644
--- a/resources/[carscripts]/lc_fuel/lang/de.lua
+++ b/resources/[carscripts]/lc_fuel/lang/de.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['de'] = {
- ['markers'] = {
- ['open_refuel'] = "Drücke ~INPUT_CONTEXT~, um zu tanken",
- ['open_recharge'] = "Drücke ~INPUT_CONTEXT~, um aufzuladen",
- ['interact_with_vehicle'] = "Drücke ~y~E~w~, um zu interagieren",
- ['return_nozzle'] = "Drücke ~INPUT_CONTEXT~, um die Zapfpistole zurückzugeben",
- },
- ['target'] = {
- ['open_refuel'] = "Tankmenü öffnen",
- ['open_recharge'] = "Lademenü öffnen",
- ['start_refuel'] = "Fahrzeug betanken",
- ['stop_refuel'] = "Tanken beenden",
- ['return_nozzle'] = "Zapfpistole zurückgeben",
- },
- ['blip_text'] = "Tankstelle",
- ['not_enough_refuel'] = "Sie haben den gesamten bezahlten Kraftstoff bereits verbraucht. Bitte kaufen Sie bei Bedarf zusätzlichen Treibstoff",
- ['invalid_value'] = "Ungültiger Wert",
- ['not_enough_money'] = "Du hast nicht genug $%s geld um das zu Bezahlen",
- ['not_enough_stock'] = "Diese Tankstelle verfügt nicht über genügend Lagerbestände, um diese Aktion durchzuführen",
- ['refuel_paid'] = "$%s bezahlt zum Tanken",
- ['returned_fuel'] = "Du hast %sL Kraftstoff zurückgegeben und $%s zurückerhalten",
- ['returned_charge'] = "Du hast %skWh Ladung zurückgegeben und $%s zurückerhalten",
- ['jerry_can_paid'] = "$%s bezahlt für den Kanister",
- ['too_far_away'] = "Sie sind zu weit von der Zapfseule entfernt",
- ['vehicle_refueled'] = "Sie haben %sL ins Fahrzeug getankt",
- ['vehicle_recharged'] = "Sie haben %skWh im Fahrzeug aufgeladen",
- ['vehicle_tank_full'] = "Auto ist voll getankt",
- ['vehicle_tank_emptied'] = "Fahrzeugtank ist leer",
- ['vehicle_not_found'] = "Fahrzeug konnte nicht gefunden werden",
- ['pump_not_found'] = "Zapfseule konnte nicht gefunden werden",
- ['vehicle_wrong_fuel'] = "Sie haben für dieses Fahrzeug den falschen Kraftstofftyp verwendet, was zu einer Panne geführt hat.",
- ['incompatible_fuel'] = "Inkompatibler Kraftstofftyp erkannt. Bitte wählen Sie die richtige Betankungsoption für Ihr Fahrzeug aus.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "Benzinkanister verkauft (%s Liter)",
- ['balance_fuel'] = "Treibstoff verkauft (%s Liter)",
- ['balance_electric'] = "Elektrische Ladung verkauft (%s kWh)",
- ['refund_fuel'] = "Kraftstoff erstattet (%s Liter)",
- ['refund_electric'] = "Stromladung erstattet (%s kWh)",
- }
-}
+if not Lang then Lang = {} end
+Lang['de'] = {
+ ['markers'] = {
+ ['open_refuel'] = "Drücke ~INPUT_CONTEXT~, um zu tanken",
+ ['open_recharge'] = "Drücke ~INPUT_CONTEXT~, um aufzuladen",
+ ['interact_with_vehicle'] = "Drücke ~y~E~w~, um zu interagieren",
+ ['return_nozzle'] = "Drücke ~INPUT_CONTEXT~, um die Zapfpistole zurückzugeben",
+ },
+ ['target'] = {
+ ['open_refuel'] = "Tankmenü öffnen",
+ ['open_recharge'] = "Lademenü öffnen",
+ ['start_refuel'] = "Fahrzeug betanken",
+ ['stop_refuel'] = "Tanken beenden",
+ ['return_nozzle'] = "Zapfpistole zurückgeben",
+ },
+ ['blip_text'] = "Tankstelle",
+ ['not_enough_refuel'] = "Sie haben den gesamten bezahlten Kraftstoff bereits verbraucht. Bitte kaufen Sie bei Bedarf zusätzlichen Treibstoff",
+ ['invalid_value'] = "Ungültiger Wert",
+ ['not_enough_money'] = "Du hast nicht genug $%s geld um das zu Bezahlen",
+ ['not_enough_stock'] = "Diese Tankstelle verfügt nicht über genügend Lagerbestände, um diese Aktion durchzuführen",
+ ['refuel_paid'] = "$%s bezahlt zum Tanken",
+ ['returned_fuel'] = "Du hast %sL Kraftstoff zurückgegeben und $%s zurückerhalten",
+ ['returned_charge'] = "Du hast %skWh Ladung zurückgegeben und $%s zurückerhalten",
+ ['jerry_can_paid'] = "$%s bezahlt für den Kanister",
+ ['too_far_away'] = "Sie sind zu weit von der Zapfseule entfernt",
+ ['vehicle_refueled'] = "Sie haben %sL ins Fahrzeug getankt",
+ ['vehicle_recharged'] = "Sie haben %skWh im Fahrzeug aufgeladen",
+ ['vehicle_tank_full'] = "Auto ist voll getankt",
+ ['vehicle_tank_emptied'] = "Fahrzeugtank ist leer",
+ ['vehicle_not_found'] = "Fahrzeug konnte nicht gefunden werden",
+ ['pump_not_found'] = "Zapfseule konnte nicht gefunden werden",
+ ['vehicle_wrong_fuel'] = "Sie haben für dieses Fahrzeug den falschen Kraftstofftyp verwendet, was zu einer Panne geführt hat.",
+ ['incompatible_fuel'] = "Inkompatibler Kraftstofftyp erkannt. Bitte wählen Sie die richtige Betankungsoption für Ihr Fahrzeug aus.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "Benzinkanister verkauft (%s Liter)",
+ ['balance_fuel'] = "Treibstoff verkauft (%s Liter)",
+ ['balance_electric'] = "Elektrische Ladung verkauft (%s kWh)",
+ ['refund_fuel'] = "Kraftstoff erstattet (%s Liter)",
+ ['refund_electric'] = "Stromladung erstattet (%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "Kraftstoffart: %s",
+ ['electric'] = "Elektrisch",
+ ['regular'] = "Regulär",
+ ['plus'] = "Plus",
+ ['premium'] = "Premium",
+ ['diesel'] = "Diesel",
+ },
+}
diff --git a/resources/[carscripts]/lc_fuel/lang/en.lua b/resources/[carscripts]/lc_fuel/lang/en.lua
index a0137aa61..4de19dddd 100644
--- a/resources/[carscripts]/lc_fuel/lang/en.lua
+++ b/resources/[carscripts]/lc_fuel/lang/en.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['en'] = {
- ['markers'] = {
- ['open_refuel'] = "Press ~INPUT_CONTEXT~ to refuel",
- ['open_recharge'] = "Press ~INPUT_CONTEXT~ to recharge",
- ['interact_with_vehicle'] = "Press ~y~E~w~ to interact",
- ['return_nozzle'] = "Press ~INPUT_CONTEXT~ to return the nozzle",
- },
- ['target'] = {
- ['open_refuel'] = "Open refuel menu",
- ['open_recharge'] = "Open recharge menu",
- ['start_refuel'] = "Refuel vehicle",
- ['stop_refuel'] = "Stop refuel",
- ['return_nozzle'] = "Return the nozzle",
- },
- ['blip_text'] = "Gas stations",
- ['not_enough_refuel'] = "You've already used all the fuel you paid for. Please purchase additional fuel if needed",
- ['invalid_value'] = "Invalid value",
- ['not_enough_money'] = "You don't have $%s to pay this",
- ['not_enough_stock'] = "This gas station don't have enough stock to perform this action",
- ['refuel_paid'] = "Paid $%s for this refuel",
- ['returned_fuel'] = "You've returned %sL of fuel and received back $%s",
- ['returned_charge'] = "You've returned %skWh of fuel and received back $%s",
- ['jerry_can_paid'] = "Paid $%s for this jerry can",
- ['too_far_away'] = "You are too far from the pump",
- ['vehicle_refueled'] = "You refueled %sL in the vehicle",
- ['vehicle_recharged'] = "You recharged %skWh in the vehicle",
- ['vehicle_tank_full'] = "Vehicle tank is full",
- ['vehicle_tank_emptied'] = "Vehicle tank emptied",
- ['vehicle_not_found'] = "Vehicle not found",
- ['pump_not_found'] = "Pump not found",
- ['vehicle_wrong_fuel'] = "You used the wrong fuel type for this vehicle, causing it to break down.",
- ['incompatible_fuel'] = "Incompatible fuel type detected. Please select the correct refueling option for your vehicle.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "Gas can sold (%s Liters)",
- ['balance_fuel'] = "Fuel sold (%s Liters)",
- ['balance_electric'] = "Electric charge sold (%s kWh)",
- ['refund_fuel'] = "Fuel refunded (%s Liters)",
- ['refund_electric'] = "Electric charge refunded (%s kWh)",
- }
+if not Lang then Lang = {} end
+Lang['en'] = {
+ ['markers'] = {
+ ['open_refuel'] = "Press ~INPUT_CONTEXT~ to refuel",
+ ['open_recharge'] = "Press ~INPUT_CONTEXT~ to recharge",
+ ['interact_with_vehicle'] = "Press ~y~E~w~ to interact",
+ ['return_nozzle'] = "Press ~INPUT_CONTEXT~ to return the nozzle",
+ },
+ ['target'] = {
+ ['open_refuel'] = "Open refuel menu",
+ ['open_recharge'] = "Open recharge menu",
+ ['start_refuel'] = "Refuel vehicle",
+ ['stop_refuel'] = "Stop refuel",
+ ['return_nozzle'] = "Return the nozzle",
+ },
+ ['blip_text'] = "Gas stations",
+ ['not_enough_refuel'] = "You've already used all the fuel you paid for. Please purchase additional fuel if needed",
+ ['invalid_value'] = "Invalid value",
+ ['not_enough_money'] = "You don't have $%s to pay this",
+ ['not_enough_stock'] = "This gas station don't have enough stock to perform this action",
+ ['refuel_paid'] = "Paid $%s for this refuel",
+ ['returned_fuel'] = "You've returned %sL of fuel and received back $%s",
+ ['returned_charge'] = "You've returned %skWh of fuel and received back $%s",
+ ['jerry_can_paid'] = "Paid $%s for this jerry can",
+ ['too_far_away'] = "You are too far from the pump",
+ ['vehicle_refueled'] = "You refueled %sL in the vehicle",
+ ['vehicle_recharged'] = "You recharged %skWh in the vehicle",
+ ['vehicle_tank_full'] = "Vehicle tank is full",
+ ['vehicle_tank_emptied'] = "Vehicle tank emptied",
+ ['vehicle_not_found'] = "Vehicle not found",
+ ['pump_not_found'] = "Pump not found",
+ ['vehicle_wrong_fuel'] = "You used the wrong fuel type for this vehicle, causing it to break down.",
+ ['incompatible_fuel'] = "Incompatible fuel type detected. Please select the correct refueling option for your vehicle.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "Gas can sold (%s Liters)",
+ ['balance_fuel'] = "Fuel sold (%s Liters)",
+ ['balance_electric'] = "Electric charge sold (%s kWh)",
+ ['refund_fuel'] = "Fuel refunded (%s Liters)",
+ ['refund_electric'] = "Electric charge refunded (%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "Fuel Type: %s",
+ ['electric'] = "Electric",
+ ['regular'] = "Regular",
+ ['plus'] = "Plus",
+ ['premium'] = "Premium",
+ ['diesel'] = "Diesel",
+ },
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/lang/es.lua b/resources/[carscripts]/lc_fuel/lang/es.lua
index 0f57b0fb2..440407716 100644
--- a/resources/[carscripts]/lc_fuel/lang/es.lua
+++ b/resources/[carscripts]/lc_fuel/lang/es.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['es'] = {
- ['markers'] = {
- ['open_refuel'] = "Pulsa ~INPUT_CONTEXT~ para repostar",
- ['open_recharge'] = "Pulsa ~INPUT_CONTEXT~ para cargar",
- ['interact_with_vehicle'] = "Pulsa ~y~E~w~ para interactuar",
- ['return_nozzle'] = "Pulsa ~INPUT_CONTEXT~ para devolver la manguera",
- },
- ['target'] = {
- ['open_refuel'] = "Abrir menú de repostaje",
- ['open_recharge'] = "Abrir menú de carga",
- ['start_refuel'] = "Repostar vehículo",
- ['stop_refuel'] = "Detener repostaje",
- ['return_nozzle'] = "Devolver la manguera",
- },
- ['blip_text'] = "Gasolineras",
- ['not_enough_refuel'] = "Ya has usado todo el combustible que pagaste. Compra más combustible si es necesario",
- ['invalid_value'] = "Valor inválido",
- ['not_enough_money'] = "No tienes $%s para pagar esto",
- ['not_enough_stock'] = "Esta gasolinera no tiene suficiente stock para realizar esta acción",
- ['refuel_paid'] = "Pagaste $%s por este repostaje",
- ['returned_fuel'] = "Has devuelto %sL de combustible y recibido $%s",
- ['returned_charge'] = "Has devuelto %skWh de carga y recibido $%s",
- ['jerry_can_paid'] = "Pagaste $%s por este bidón de gasolina",
- ['too_far_away'] = "Estás demasiado lejos del surtidor",
- ['vehicle_refueled'] = "Repostaste %sL en el vehículo",
- ['vehicle_recharged'] = "Recargaste %skWh en el vehículo",
- ['vehicle_tank_full'] = "El tanque del vehículo está lleno",
- ['vehicle_tank_emptied'] = "El tanque del vehículo se ha vaciado",
- ['vehicle_not_found'] = "Vehículo no encontrado",
- ['pump_not_found'] = "Surtidor no encontrado",
- ['vehicle_wrong_fuel'] = "Usaste el tipo de combustible incorrecto para este vehículo, causando que se averíe.",
- ['incompatible_fuel'] = "Tipo de combustible incompatible detectado. Por favor, selecciona la opción de repostaje correcta para tu vehículo.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "Bidón de gasolina vendido (%s Litros)",
- ['balance_fuel'] = "Combustible vendido (%s Litros)",
- ['balance_electric'] = "Carga eléctrica vendida (%s kWh)",
- ['refund_fuel'] = "Combustible reembolsado (%s litros)",
- ['refund_electric'] = "Carga eléctrica reembolsada (%s kWh)",
- }
-}
+if not Lang then Lang = {} end
+Lang['es'] = {
+ ['markers'] = {
+ ['open_refuel'] = "Pulsa ~INPUT_CONTEXT~ para repostar",
+ ['open_recharge'] = "Pulsa ~INPUT_CONTEXT~ para cargar",
+ ['interact_with_vehicle'] = "Pulsa ~y~E~w~ para interactuar",
+ ['return_nozzle'] = "Pulsa ~INPUT_CONTEXT~ para devolver la manguera",
+ },
+ ['target'] = {
+ ['open_refuel'] = "Abrir menú de repostaje",
+ ['open_recharge'] = "Abrir menú de carga",
+ ['start_refuel'] = "Repostar vehículo",
+ ['stop_refuel'] = "Detener repostaje",
+ ['return_nozzle'] = "Devolver la manguera",
+ },
+ ['blip_text'] = "Gasolineras",
+ ['not_enough_refuel'] = "Ya has usado todo el combustible que pagaste. Compra más combustible si es necesario",
+ ['invalid_value'] = "Valor inválido",
+ ['not_enough_money'] = "No tienes $%s para pagar esto",
+ ['not_enough_stock'] = "Esta gasolinera no tiene suficiente stock para realizar esta acción",
+ ['refuel_paid'] = "Pagaste $%s por este repostaje",
+ ['returned_fuel'] = "Has devuelto %sL de combustible y recibido $%s",
+ ['returned_charge'] = "Has devuelto %skWh de carga y recibido $%s",
+ ['jerry_can_paid'] = "Pagaste $%s por este bidón de gasolina",
+ ['too_far_away'] = "Estás demasiado lejos del surtidor",
+ ['vehicle_refueled'] = "Repostaste %sL en el vehículo",
+ ['vehicle_recharged'] = "Recargaste %skWh en el vehículo",
+ ['vehicle_tank_full'] = "El tanque del vehículo está lleno",
+ ['vehicle_tank_emptied'] = "El tanque del vehículo se ha vaciado",
+ ['vehicle_not_found'] = "Vehículo no encontrado",
+ ['pump_not_found'] = "Surtidor no encontrado",
+ ['vehicle_wrong_fuel'] = "Usaste el tipo de combustible incorrecto para este vehículo, causando que se averíe.",
+ ['incompatible_fuel'] = "Tipo de combustible incompatible detectado. Por favor, selecciona la opción de repostaje correcta para tu vehículo.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "Bidón de gasolina vendido (%s Litros)",
+ ['balance_fuel'] = "Combustible vendido (%s Litros)",
+ ['balance_electric'] = "Carga eléctrica vendida (%s kWh)",
+ ['refund_fuel'] = "Combustible reembolsado (%s litros)",
+ ['refund_electric'] = "Carga eléctrica reembolsada (%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "Tipo de combustible: %s",
+ ['electric'] = "Eléctrico",
+ ['regular'] = "Sin plomo",
+ ['plus'] = "Plus",
+ ['premium'] = "Premium",
+ ['diesel'] = "Diésel",
+ },
+}
diff --git a/resources/[carscripts]/lc_fuel/lang/fr.lua b/resources/[carscripts]/lc_fuel/lang/fr.lua
index b22f15033..e78a40f70 100644
--- a/resources/[carscripts]/lc_fuel/lang/fr.lua
+++ b/resources/[carscripts]/lc_fuel/lang/fr.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['fr'] = {
- ['markers'] = {
- ['open_refuel'] = "Appuyez sur ~INPUT_CONTEXT~ pour faire le plein",
- ['open_recharge'] = "Appuyez sur ~INPUT_CONTEXT~ pour recharger",
- ['interact_with_vehicle'] = "Appuyez sur ~y~E~w~ pour interagir",
- ['return_nozzle'] = "Appuyez sur ~INPUT_CONTEXT~ pour remettre le pistolet",
- },
- ['target'] = {
- ['open_refuel'] = "Ouvrir le menu de ravitaillement",
- ['open_recharge'] = "Ouvrir le menu de recharge",
- ['start_refuel'] = "Faire le plein du véhicule",
- ['stop_refuel'] = "Arrêter le ravitaillement",
- ['return_nozzle'] = "Ranger le pistolet",
- },
- ['blip_text'] = "Stations-service",
- ['not_enough_refuel'] = "Vous avez déjà utilisé tout le carburant que vous avez payé. Veuillez acheter plus de carburant si nécessaire",
- ['invalid_value'] = "Valeur invalide",
- ['not_enough_money'] = "Vous n'avez pas $%s pour payer cela",
- ['not_enough_stock'] = "Cette station-service n'a pas assez de stock pour effectuer cette action",
- ['refuel_paid'] = "Vous avez payé $%s pour ce ravitaillement",
- ['returned_fuel'] = "Vous avez rendu %sL de carburant et reçu $%s",
- ['returned_charge'] = "Vous avez rendu %skWh de charge et reçu $%s",
- ['jerry_can_paid'] = "Vous avez payé $%s pour ce bidon d'essence",
- ['too_far_away'] = "Vous êtes trop loin de la pompe",
- ['vehicle_refueled'] = "Vous avez mis %sL dans le véhicule",
- ['vehicle_recharged'] = "Vous avez rechargé %skWh dans le véhicule",
- ['vehicle_tank_full'] = "Le réservoir du véhicule est plein",
- ['vehicle_tank_emptied'] = "Le réservoir du véhicule est vide",
- ['vehicle_not_found'] = "Véhicule non trouvé",
- ['pump_not_found'] = "Pompe non trouvée",
- ['vehicle_wrong_fuel'] = "Vous avez utilisé le mauvais type de carburant pour ce véhicule, ce qui l'a endommagé.",
- ['incompatible_fuel'] = "Type de carburant incompatible détecté. Veuillez sélectionner la bonne option de ravitaillement pour votre véhicule.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "Bidon d'essence vendu (%s Litres)",
- ['balance_fuel'] = "Carburant vendu (%s Litres)",
- ['balance_electric'] = "Charge électrique vendue (%s kWh)",
- ['refund_fuel'] = "Carburant remboursé (%s litres)",
- ['refund_electric'] = "Recharge électrique remboursée (%s kWh)",
- }
+if not Lang then Lang = {} end
+Lang['fr'] = {
+ ['markers'] = {
+ ['open_refuel'] = "Appuyez sur ~INPUT_CONTEXT~ pour faire le plein",
+ ['open_recharge'] = "Appuyez sur ~INPUT_CONTEXT~ pour recharger",
+ ['interact_with_vehicle'] = "Appuyez sur ~y~E~w~ pour interagir",
+ ['return_nozzle'] = "Appuyez sur ~INPUT_CONTEXT~ pour remettre le pistolet",
+ },
+ ['target'] = {
+ ['open_refuel'] = "Ouvrir le menu de ravitaillement",
+ ['open_recharge'] = "Ouvrir le menu de recharge",
+ ['start_refuel'] = "Faire le plein du véhicule",
+ ['stop_refuel'] = "Arrêter le ravitaillement",
+ ['return_nozzle'] = "Ranger le pistolet",
+ },
+ ['blip_text'] = "Stations-service",
+ ['not_enough_refuel'] = "Vous avez déjà utilisé tout le carburant que vous avez payé. Veuillez acheter plus de carburant si nécessaire",
+ ['invalid_value'] = "Valeur invalide",
+ ['not_enough_money'] = "Vous n'avez pas $%s pour payer cela",
+ ['not_enough_stock'] = "Cette station-service n'a pas assez de stock pour effectuer cette action",
+ ['refuel_paid'] = "Vous avez payé $%s pour ce ravitaillement",
+ ['returned_fuel'] = "Vous avez rendu %sL de carburant et reçu $%s",
+ ['returned_charge'] = "Vous avez rendu %skWh de charge et reçu $%s",
+ ['jerry_can_paid'] = "Vous avez payé $%s pour ce bidon d'essence",
+ ['too_far_away'] = "Vous êtes trop loin de la pompe",
+ ['vehicle_refueled'] = "Vous avez mis %sL dans le véhicule",
+ ['vehicle_recharged'] = "Vous avez rechargé %skWh dans le véhicule",
+ ['vehicle_tank_full'] = "Le réservoir du véhicule est plein",
+ ['vehicle_tank_emptied'] = "Le réservoir du véhicule est vide",
+ ['vehicle_not_found'] = "Véhicule non trouvé",
+ ['pump_not_found'] = "Pompe non trouvée",
+ ['vehicle_wrong_fuel'] = "Vous avez utilisé le mauvais type de carburant pour ce véhicule, ce qui l'a endommagé.",
+ ['incompatible_fuel'] = "Type de carburant incompatible détecté. Veuillez sélectionner la bonne option de ravitaillement pour votre véhicule.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "Bidon d'essence vendu (%s Litres)",
+ ['balance_fuel'] = "Carburant vendu (%s Litres)",
+ ['balance_electric'] = "Charge électrique vendue (%s kWh)",
+ ['refund_fuel'] = "Carburant remboursé (%s litres)",
+ ['refund_electric'] = "Recharge électrique remboursée (%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "Type de carburant : %s",
+ ['electric'] = "Électrique",
+ ['regular'] = "Ordinaire",
+ ['plus'] = "Plus",
+ ['premium'] = "Premium",
+ ['diesel'] = "Diesel",
+ },
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/lang/ja.lua b/resources/[carscripts]/lc_fuel/lang/ja.lua
index bf3cf5ca5..f42e9d4fc 100644
--- a/resources/[carscripts]/lc_fuel/lang/ja.lua
+++ b/resources/[carscripts]/lc_fuel/lang/ja.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['ja'] = {
- ['markers'] = {
- ['open_refuel'] = "~INPUT_CONTEXT~を押して燃料を補給します",
- ['open_recharge'] = "~INPUT_CONTEXT~を押して充電",
- ['interact_with_vehicle'] = "~y~E~w~を押して車両と操作",
- ['return_nozzle'] = "~INPUT_CONTEXT~を押してノズルを戻す",
- },
- ['target'] = {
- ['open_refuel'] = "燃料補給メニューを開く",
- ['open_recharge'] = "充電メニューを開く",
- ['start_refuel'] = "車両に燃料補給",
- ['stop_refuel'] = "燃料補給を停止",
- ['return_nozzle'] = "ノズルを戻す",
- },
- ['blip_text'] = "ガソリンスタンド",
- ['not_enough_refuel'] = "既に支払った燃料を使い切っています。必要であれば追加購入してください。",
- ['invalid_value'] = "無効な値です",
- ['not_enough_money'] = "この支払いには$%sが不足しています",
- ['not_enough_stock'] = "このガソリンスタンドでは在庫が不足しているため、この操作は実行できません",
- ['refuel_paid'] = "この燃料補給に$%s支払いました",
- ['returned_fuel'] = "燃料を%sL返却し、$%sを受け取りました",
- ['returned_charge'] = "電力を%skWh返却し、$%sを受け取りました",
- ['jerry_can_paid'] = "このガソリン缶に$%s支払いました",
- ['too_far_away'] = "ポンプから離れすぎています",
- ['vehicle_refueled'] = "車両に%sLの燃料を補給しました",
- ['vehicle_recharged'] = "車両に%s kWhの充電を行いました",
- ['vehicle_tank_full'] = "車両のタンクが満タンです",
- ['vehicle_tank_emptied'] = "車両のタンクが空になりました",
- ['vehicle_not_found'] = "車両が見つかりませんでした",
- ['pump_not_found'] = "ポンプが見つかりませんでした",
- ['vehicle_wrong_fuel'] = "この車両には間違った燃料タイプを使用したため、故障しました。",
- ['incompatible_fuel'] = "互換性のない燃料タイプが検出されました。正しい燃料補給オプションを選択してください。",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "ガソリン缶販売 (%s L)",
- ['balance_fuel'] = "燃料販売 (%s L)",
- ['balance_electric'] = "電気充電販売 (%s kWh)",
- ['refund_fuel'] = "燃料が返金されました(%sリットル)",
- ['refund_electric'] = "電気充電が返金されました(%s kWh)",
- }
+if not Lang then Lang = {} end
+Lang['ja'] = {
+ ['markers'] = {
+ ['open_refuel'] = "~INPUT_CONTEXT~を押して燃料を補給します",
+ ['open_recharge'] = "~INPUT_CONTEXT~を押して充電",
+ ['interact_with_vehicle'] = "~y~E~w~を押して車両と操作",
+ ['return_nozzle'] = "~INPUT_CONTEXT~を押してノズルを戻す",
+ },
+ ['target'] = {
+ ['open_refuel'] = "燃料補給メニューを開く",
+ ['open_recharge'] = "充電メニューを開く",
+ ['start_refuel'] = "車両に燃料補給",
+ ['stop_refuel'] = "燃料補給を停止",
+ ['return_nozzle'] = "ノズルを戻す",
+ },
+ ['blip_text'] = "ガソリンスタンド",
+ ['not_enough_refuel'] = "既に支払った燃料を使い切っています。必要であれば追加購入してください。",
+ ['invalid_value'] = "無効な値です",
+ ['not_enough_money'] = "この支払いには$%sが不足しています",
+ ['not_enough_stock'] = "このガソリンスタンドでは在庫が不足しているため、この操作は実行できません",
+ ['refuel_paid'] = "この燃料補給に$%s支払いました",
+ ['returned_fuel'] = "燃料を%sL返却し、$%sを受け取りました",
+ ['returned_charge'] = "電力を%skWh返却し、$%sを受け取りました",
+ ['jerry_can_paid'] = "このガソリン缶に$%s支払いました",
+ ['too_far_away'] = "ポンプから離れすぎています",
+ ['vehicle_refueled'] = "車両に%sLの燃料を補給しました",
+ ['vehicle_recharged'] = "車両に%s kWhの充電を行いました",
+ ['vehicle_tank_full'] = "車両のタンクが満タンです",
+ ['vehicle_tank_emptied'] = "車両のタンクが空になりました",
+ ['vehicle_not_found'] = "車両が見つかりませんでした",
+ ['pump_not_found'] = "ポンプが見つかりませんでした",
+ ['vehicle_wrong_fuel'] = "この車両には間違った燃料タイプを使用したため、故障しました。",
+ ['incompatible_fuel'] = "互換性のない燃料タイプが検出されました。正しい燃料補給オプションを選択してください。",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "ガソリン缶販売 (%s L)",
+ ['balance_fuel'] = "燃料販売 (%s L)",
+ ['balance_electric'] = "電気充電販売 (%s kWh)",
+ ['refund_fuel'] = "燃料が返金されました(%sリットル)",
+ ['refund_electric'] = "電気充電が返金されました(%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "燃料の種類: %s",
+ ['electric'] = "電気",
+ ['regular'] = "レギュラー",
+ ['plus'] = "プラス",
+ ['premium'] = "プレミアム",
+ ['diesel'] = "ディーゼル",
+ },
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/lang/tr.lua b/resources/[carscripts]/lc_fuel/lang/tr.lua
index b6b808b7d..3766d6010 100644
--- a/resources/[carscripts]/lc_fuel/lang/tr.lua
+++ b/resources/[carscripts]/lc_fuel/lang/tr.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['tr'] = {
- ['markers'] = {
- ['open_refuel'] = "Yakıt almak için ~INPUT_CONTEXT~ tuşuna basın",
- ['open_recharge'] = "Şarj etmek için ~INPUT_CONTEXT~ tuşuna basın",
- ['interact_with_vehicle'] = "Etkileşim için ~y~E~w~ tuşuna basın",
- ['return_nozzle'] = "Tabancayı geri koymak için ~INPUT_CONTEXT~ tuşuna basın",
- },
- ['target'] = {
- ['open_refuel'] = "Yakıt menüsünü aç",
- ['open_recharge'] = "Şarj menüsünü aç",
- ['start_refuel'] = "Araca yakıt doldur",
- ['stop_refuel'] = "Yakıt doldurmayı durdur",
- ['return_nozzle'] = "Tabancayı geri koy",
- },
- ['blip_text'] = "Benzin istasyonları",
- ['not_enough_refuel'] = "Zaten ödediğiniz tüm yakıtı kullandınız. Gerekirse ek yakıt satın alın",
- ['invalid_value'] = "Geçersiz değer",
- ['not_enough_money'] = "Bunu ödemek için $%s paranız yok",
- ['not_enough_stock'] = "Bu benzin istasyonunda bu işlemi gerçekleştirmek için yeterli stok yok",
- ['refuel_paid'] = "Bu yakıt için $%s ödendi",
- ['returned_fuel'] = "%sL yakıt iade ettiniz ve $%s geri aldınız",
- ['returned_charge'] = "%skWh şarj iade ettiniz ve $%s geri aldınız",
- ['jerry_can_paid'] = "Bu bidon için $%s ödendi",
- ['too_far_away'] = "Pompadan çok uzaktasınız",
- ['vehicle_refueled'] = "Araca %sL yakıt dolduruldu",
- ['vehicle_recharged'] = "Araca %skWh şarj yapıldı",
- ['vehicle_tank_full'] = "Araç deposu dolu",
- ['vehicle_tank_emptied'] = "Araç deposu boşaltıldı",
- ['vehicle_not_found'] = "Araç bulunamadı",
- ['pump_not_found'] = "Pompa bulunamadı",
- ['vehicle_wrong_fuel'] = "Bu araç için yanlış yakıt kullandınız ve aracınız bozuldu.",
- ['incompatible_fuel'] = "Uyumsuz yakıt türü tespit edildi. Lütfen aracınız için doğru yakıt seçeneğini seçin.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "Yakıt bidonu satıldı (%s Litre)",
- ['balance_fuel'] = "Yakıt satıldı (%s Litre)",
- ['balance_electric'] = "Elektrik şarjı satıldı (%s kWh)",
- ['refund_fuel'] = "Yakıt iade edildi (%s litre)",
- ['refund_electric'] = "Elektrik şarjı iade edildi (%s kWh)",
- }
-}
+if not Lang then Lang = {} end
+Lang['tr'] = {
+ ['markers'] = {
+ ['open_refuel'] = "Yakıt almak için ~INPUT_CONTEXT~ tuşuna basın",
+ ['open_recharge'] = "Şarj etmek için ~INPUT_CONTEXT~ tuşuna basın",
+ ['interact_with_vehicle'] = "Etkileşim için ~y~E~w~ tuşuna basın",
+ ['return_nozzle'] = "Tabancayı geri koymak için ~INPUT_CONTEXT~ tuşuna basın",
+ },
+ ['target'] = {
+ ['open_refuel'] = "Yakıt menüsünü aç",
+ ['open_recharge'] = "Şarj menüsünü aç",
+ ['start_refuel'] = "Araca yakıt doldur",
+ ['stop_refuel'] = "Yakıt doldurmayı durdur",
+ ['return_nozzle'] = "Tabancayı geri koy",
+ },
+ ['blip_text'] = "Benzin istasyonları",
+ ['not_enough_refuel'] = "Zaten ödediğiniz tüm yakıtı kullandınız. Gerekirse ek yakıt satın alın",
+ ['invalid_value'] = "Geçersiz değer",
+ ['not_enough_money'] = "Bunu ödemek için $%s paranız yok",
+ ['not_enough_stock'] = "Bu benzin istasyonunda bu işlemi gerçekleştirmek için yeterli stok yok",
+ ['refuel_paid'] = "Bu yakıt için $%s ödendi",
+ ['returned_fuel'] = "%sL yakıt iade ettiniz ve $%s geri aldınız",
+ ['returned_charge'] = "%skWh şarj iade ettiniz ve $%s geri aldınız",
+ ['jerry_can_paid'] = "Bu bidon için $%s ödendi",
+ ['too_far_away'] = "Pompadan çok uzaktasınız",
+ ['vehicle_refueled'] = "Araca %sL yakıt dolduruldu",
+ ['vehicle_recharged'] = "Araca %skWh şarj yapıldı",
+ ['vehicle_tank_full'] = "Araç deposu dolu",
+ ['vehicle_tank_emptied'] = "Araç deposu boşaltıldı",
+ ['vehicle_not_found'] = "Araç bulunamadı",
+ ['pump_not_found'] = "Pompa bulunamadı",
+ ['vehicle_wrong_fuel'] = "Bu araç için yanlış yakıt kullandınız ve aracınız bozuldu.",
+ ['incompatible_fuel'] = "Uyumsuz yakıt türü tespit edildi. Lütfen aracınız için doğru yakıt seçeneğini seçin.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "Yakıt bidonu satıldı (%s Litre)",
+ ['balance_fuel'] = "Yakıt satıldı (%s Litre)",
+ ['balance_electric'] = "Elektrik şarjı satıldı (%s kWh)",
+ ['refund_fuel'] = "Yakıt iade edildi (%s litre)",
+ ['refund_electric'] = "Elektrik şarjı iade edildi (%s kWh)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "Yakıt Türü: %s",
+ ['electric'] = "Elektrikli",
+ ['regular'] = "Normal",
+ ['plus'] = "Plus",
+ ['premium'] = "Premium",
+ ['diesel'] = "Dizel",
+ },
+}
diff --git a/resources/[carscripts]/lc_fuel/lang/zh-cn.lua b/resources/[carscripts]/lc_fuel/lang/zh-cn.lua
index b2094525f..fe13b87e9 100644
--- a/resources/[carscripts]/lc_fuel/lang/zh-cn.lua
+++ b/resources/[carscripts]/lc_fuel/lang/zh-cn.lua
@@ -1,41 +1,49 @@
-if not Lang then Lang = {} end
-Lang['zh-cn'] = {
- ['markers'] = {
- ['open_refuel'] = "按下 ~INPUT_CONTEXT~ 进行加油",
- ['open_recharge'] = "按下 ~INPUT_CONTEXT~ 进行充电",
- ['interact_with_vehicle'] = "按下 ~y~E~w~ 与车辆交互",
- ['return_nozzle'] = "按下 ~INPUT_CONTEXT~ 归还油枪",
- },
- ['target'] = {
- ['open_refuel'] = "进行加油",
- ['open_recharge'] = "进行充电",
- ['start_refuel'] = "开始加油",
- ['stop_refuel'] = "终止加油",
- ['return_nozzle'] = "归还油枪",
- },
- ['blip_text'] = "加油站",
- ['not_enough_refuel'] = "您已用完所支付的燃油。如需继续,请购买更多燃油",
- ['invalid_value'] = "无效数值",
- ['not_enough_money'] = "您的账户余额不足支付当前金额 ($%s) ",
- ['not_enough_stock'] = "本站点当前无充足库存完成该操作",
- ['refuel_paid'] = "本次燃油补给消费 $%s",
- ['returned_fuel'] = "你已归还%s升燃料,并收到$%s",
- ['returned_charge'] = "你已归还%skWh电量,并收到$%s",
- ['jerry_can_paid'] = "本次便携油桶购买消费 $%s",
- ['too_far_away'] = "您与加油设备间距超出操作范围!",
- ['vehicle_refueled'] = "车辆成功加注燃油 %s 升(L)",
- ['vehicle_recharged'] = "车辆成功充入电能 %s 千瓦时(kWh)",
- ['vehicle_tank_full'] = "车辆油箱已达最大容量",
- ['vehicle_tank_emptied'] = "车辆油箱燃油已全部清空",
- ['vehicle_not_found'] = "未检测到关联载具",
- ['pump_not_found'] = "未检测到可用加油设备",
- ['vehicle_wrong_fuel'] = "误用燃油类型导致车辆受损, 请立即停止操作!",
- ['incompatible_fuel'] = "燃油类型与车辆配置不匹配,请选择适配的加油方案.",
- ['owned_gas_stations'] = {
- ['balance_jerry_can'] = "便携式油桶销售量 (%s 升)",
- ['balance_fuel'] = "燃油销售总量 (%s 升)",
- ['balance_electric'] = "电能销售收入 (%s 千瓦时)",
- ['refund_fuel'] = "燃料已退款(%s 升)",
- ['refund_electric'] = "电力已退款(%s 千瓦时)",
- }
+if not Lang then Lang = {} end
+Lang['zh-cn'] = {
+ ['markers'] = {
+ ['open_refuel'] = "按下 ~INPUT_CONTEXT~ 进行加油",
+ ['open_recharge'] = "按下 ~INPUT_CONTEXT~ 进行充电",
+ ['interact_with_vehicle'] = "按下 ~y~E~w~ 与车辆交互",
+ ['return_nozzle'] = "按下 ~INPUT_CONTEXT~ 归还油枪",
+ },
+ ['target'] = {
+ ['open_refuel'] = "进行加油",
+ ['open_recharge'] = "进行充电",
+ ['start_refuel'] = "开始加油",
+ ['stop_refuel'] = "终止加油",
+ ['return_nozzle'] = "归还油枪",
+ },
+ ['blip_text'] = "加油站",
+ ['not_enough_refuel'] = "您已用完所支付的燃油。如需继续,请购买更多燃油",
+ ['invalid_value'] = "无效数值",
+ ['not_enough_money'] = "您的账户余额不足支付当前金额 ($%s) ",
+ ['not_enough_stock'] = "本站点当前无充足库存完成该操作",
+ ['refuel_paid'] = "本次燃油补给消费 $%s",
+ ['returned_fuel'] = "你已归还%s升燃料,并收到$%s",
+ ['returned_charge'] = "你已归还%skWh电量,并收到$%s",
+ ['jerry_can_paid'] = "本次便携油桶购买消费 $%s",
+ ['too_far_away'] = "您与加油设备间距超出操作范围!",
+ ['vehicle_refueled'] = "车辆成功加注燃油 %s 升(L)",
+ ['vehicle_recharged'] = "车辆成功充入电能 %s 千瓦时(kWh)",
+ ['vehicle_tank_full'] = "车辆油箱已达最大容量",
+ ['vehicle_tank_emptied'] = "车辆油箱燃油已全部清空",
+ ['vehicle_not_found'] = "未检测到关联载具",
+ ['pump_not_found'] = "未检测到可用加油设备",
+ ['vehicle_wrong_fuel'] = "误用燃油类型导致车辆受损, 请立即停止操作!",
+ ['incompatible_fuel'] = "燃油类型与车辆配置不匹配,请选择适配的加油方案.",
+ ['owned_gas_stations'] = {
+ ['balance_jerry_can'] = "便携式油桶销售量 (%s 升)",
+ ['balance_fuel'] = "燃油销售总量 (%s 升)",
+ ['balance_electric'] = "电能销售收入 (%s 千瓦时)",
+ ['refund_fuel'] = "燃料已退款(%s 升)",
+ ['refund_electric'] = "电力已退款(%s 千瓦时)",
+ },
+ ['fuel_types'] = {
+ ['type_title'] = "燃料类型:%s",
+ ['electric'] = "电动",
+ ['regular'] = "92号燃油",
+ ['plus'] = "95号燃油",
+ ['premium'] = "98号燃油",
+ ['diesel'] = "柴油",
+ },
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/css/style.css b/resources/[carscripts]/lc_fuel/nui/css/style.css
index c2c2fda76..6d619d04d 100644
--- a/resources/[carscripts]/lc_fuel/nui/css/style.css
+++ b/resources/[carscripts]/lc_fuel/nui/css/style.css
@@ -1,1004 +1,1004 @@
-@font-face {
- font-family: 'Technology';
- font-style: normal;
- font-weight: normal;
- src: url('../fonts/Technology.woff') format('woff');
-}
-
-body {
- margin: 0;
-}
-
-/* PUMP structure */
-.gas-pump-container {
- display: flex;
- justify-content: center;
- align-items: flex-end;
- height: 100%;
- width: 100%;
- background: #00000070;
-}
-
-.gas-pump-elements-container {
- position: absolute;
- bottom: 69px;
- width: 100%;
- display: grid;
- justify-items: center;
- line-height: 18px;
-}
-
-.gas-pump-values-container {
- display: grid;
- grid-template-columns: 110px 274px 224.18px 186.52px 110px;
- white-space: nowrap;
-}
-
-.digital-text {
- color: #EBFEFF;
- font-family: Technology;
- font-size: 17px;
- letter-spacing: 1.7px;
- display: inline-block;
-}
-
-.digital-text-2 {
- color: #EBFEFF;
- text-align: center;
- font-family: Technology;
- font-size: 15px;
- font-style: normal;
- font-weight: 700;
- line-height: normal;
- letter-spacing: 1.5px;
- display: inline-block;
-}
-
-.digital-text.dark {
- color: #263D3D;
-}
-
-/* Side buttons */
-.controls-container {
- display: grid;
- justify-items: start;
- align-items: center;
- font-family: 'Lexend';
-}
-
-.controls-container > button {
- width: 37px;
- height: 37px;
- border-radius: 100px;
- border: 1px solid rgba(200, 200, 200, 0.15);
- background: rgba(0, 0, 0, 0.4);
- transition: all 0.2s ease, cursor 0.2s ease;
-
- color: #FFF;
- font-size: 15px;
- font-style: normal;
- font-weight: 600;
- line-height: normal;
-
- /* Align the text */
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.controls-container > button:hover {
- cursor: pointer;
- background: rgba(50, 50, 50, 0.4);
-}
-
-/* Interactive buttons */
-.gas-pump-interactive-button {
- position: absolute;
- bottom: 520px;
- left: 50%;
- transform: translateX(140px);
- border-radius: 100px;
- border: 1px solid rgba(255, 255, 255, 0.05);
- background: rgb(255 255 255 / 9%);
- display: inline-flex;
- padding: 7px;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-}
-
-.gas-pump-interactive-inner-button {
- width: 38px;
- height: 38px;
- border-radius: 100px;
- border: 1px solid rgba(255, 255, 255, 0.15);
- background: rgb(255 255 255 / 29%);
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-
-.gas-pump-interactive-button:hover {
- border: 1px solid rgba(255, 255, 255, 0.1);
- background: rgb(255 255 255 / 6%);
- cursor: pointer;
-}
-
-.gas-pump-interactive-button:hover .gas-pump-interactive-inner-button {
- border: 1px solid rgba(255, 255, 255, 0.25);
- background: rgb(255 255 255 / 20%);
-}
-
-/* Center side of the PUMP */
-.quantity-input-container {
- display: flex;
- justify-content: center;
- margin: 0px 15px 38px;
-}
-
-.quantity-input-container > input {
- width: 68%;
- padding: 0px 5px;
- text-align: center;
- border:none;
- background-image:none;
- background-color:transparent;
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
- outline: none;
-}
-
-/* Chrome, Safari, Edge, Opera */
-.quantity-input-container > input::-webkit-outer-spin-button,
-.quantity-input-container > input::-webkit-inner-spin-button {
- -webkit-appearance: none;
- margin: 0;
-}
-
-/* Firefox */
-.quantity-input-container > input[type=number] {
- -moz-appearance: textfield;
-}
-
-.quantity-input-container > button {
- color: #EBFEFF;
- font-family: Technology;
- font-weight: 700;
- width: 31px;
- height: 31px;
- padding: 1px;
-
- border: 2px solid #72697E;
- background: #251825;
-
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-.quantity-input-container > button:hover {
- cursor: pointer;
- background: rgba(99, 105, 105, 0.15);
-}
-.quantity-input-container > .sub {
- font-size: 25px;
-}
-.quantity-input-container > .add {
- font-size: 17px;
-}
-
-.price-per-liter {
- margin: 10px 30px 26px 15px;
-}
-
-.stock-values-container {
- display: grid;
- grid-template-columns: 50% 50%;
-}
-
-.stock-values-container > span {
- margin: 0px 14px 13px;
-}
-
-/* Right side of the PUMP */
-.money-display-container {
- padding: 22px 18px 0px 11px;
- display: grid;
- justify-items: start;
-}
-
-.bank-balance {
- margin: 6px;
-}
-
-.cash-balance {
- margin: 26px 6px 15px;
-}
-
-.confirm-button {
- color: #263D3D;
- font-family: "Lexend Zetta";
- font-weight: 800;
- letter-spacing: -2.2px;
- width: 100%;
- height: fit-content;
- padding: 6px 6px;
- font-size: 13px;
- background: #909B9C;
- border: solid 2px #697474;
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-
-.confirm-button:hover {
- cursor: pointer;
- background: #a3afb1;
-}
-
-/* Footer of the PUMP */
-.gas-pump-fuel-list-container {
- display: grid;
- grid-template-columns: 26% 26% 26% 22%;
- margin-top: 22px;
- height: 34px;
- align-items: center;
- width: 685px;
-}
-
-.fuel-type-button {
- height: -webkit-fill-available;
- background: #ffffff00;
- border: none;
- color: rgba(255, 255, 255, 0.45);
- text-align: right;
- font-family: Arial;
- font-size: 15px;
- font-weight: 700;
- padding-right: 12px;
- margin: 1px;
- transition: all 0.1s ease, color 0.1s ease;
-}
-
-.fuel-type-button:hover {
- cursor: pointer;
-}
-
-@keyframes pulseRegular {
- 0% {
- background-color: rgba(255, 255, 255, 0.15);
- box-shadow: rgb(255 255 255 / 30%) 0px 0px 8px 2px, rgb(255 255 255 / 10%) 0px 0px 4px 2px;
- }
- 50% {
- background-color: rgba(255, 255, 255, 0.35);
- box-shadow: rgb(255 255 255 / 50%) 0px 0px 12px 4px, rgb(255 255 255 / 20%) 0px 0px 6px 3px;
- }
- 100% {
- background-color: rgba(255, 255, 255, 0.15);
- box-shadow: rgb(255 255 255 / 30%) 0px 0px 8px 2px, rgb(255 255 255 / 10%) 0px 0px 4px 2px;
- }
-}
-
-@keyframes pulsePlus {
- 0% {
- background-color: rgba(0, 119, 255, 0.15);
- box-shadow: rgba(0, 119, 255, 0.2) 0px 0px 8px 2px, rgba(0, 119, 255, 0.22) 0px 0px 4px 2px;
- }
- 50% {
- background-color: rgba(0, 119, 255, 0.35);
- box-shadow: rgba(0, 119, 255, 0.5) 0px 0px 12px 4px, rgba(0, 119, 255, 0.35) 0px 0px 6px 3px;
- }
- 100% {
- background-color: rgba(0, 119, 255, 0.15);
- box-shadow: rgba(0, 119, 255, 0.2) 0px 0px 8px 2px, rgba(0, 119, 255, 0.22) 0px 0px 4px 2px;
- }
-}
-
-@keyframes pulsePremium {
- 0% {
- background-color: rgba(255, 0, 0, 0.15);
- box-shadow: rgba(255, 0, 0, 0.2) 0px 0px 8px 2px, rgba(255, 0, 0, 0.22) 0px 0px 4px 2px;
- }
- 50% {
- background-color: rgba(255, 0, 0, 0.35);
- box-shadow: rgba(255, 0, 0, 0.5) 0px 0px 12px 4px, rgba(255, 0, 0, 0.35) 0px 0px 6px 3px;
- }
- 100% {
- background-color: rgba(255, 0, 0, 0.15);
- box-shadow: rgba(255, 0, 0, 0.2) 0px 0px 8px 2px, rgba(255, 0, 0, 0.22) 0px 0px 4px 2px;
- }
-}
-
-@keyframes pulseDiesel {
- 0% {
- background-color: rgba(0, 165, 0, 0.15);
- box-shadow: rgba(0, 165, 0, 0.2) 0px 0px 8px 2px, rgba(0, 165, 0, 0.20) 0px 0px 4px 2px;
- }
- 50% {
- background-color: rgba(0, 165, 0, 0.35);
- box-shadow: rgba(0, 165, 0, 0.5) 0px 0px 12px 4px, rgba(0, 165, 0, 0.30) 0px 0px 6px 3px;
- }
- 100% {
- background-color: rgba(0, 165, 0, 0.15);
- box-shadow: rgba(0, 165, 0, 0.2) 0px 0px 8px 2px, rgba(0, 165, 0, 0.20) 0px 0px 4px 2px;
- }
-}
-
-.fuel-type-button.regular.selected,
-.fuel-type-button.regular:hover {
- background: rgba(255, 255, 255, 0.15);
- cursor: pointer;
- animation: pulseRegular 3s infinite ease-in-out;
-}
-
-.fuel-type-button.plus.selected,
-.fuel-type-button.plus:hover {
- background: rgba(0, 119, 255, 0.15);
- cursor: pointer;
- animation: pulsePlus 3s infinite ease-in-out;
-}
-
-.fuel-type-button.premium.selected,
-.fuel-type-button.premium:hover {
- background: rgba(255, 0, 0, 0.15);
- cursor: pointer;
- animation: pulsePremium 3s infinite ease-in-out;
-}
-
-.fuel-type-button.diesel.selected,
-.fuel-type-button.diesel:hover {
- background: rgba(0, 165, 0, 0.15);
- cursor: pointer;
- animation: pulseDiesel 3s infinite ease-in-out;
-}
-
-
-.fuel-type-button.regular {
- color: rgba(0, 0, 0, 0.75);
-}
-
-/* Refuel display */
-.refuel-display-body {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: end;
- justify-content: center;
- z-index: 1000;
- font-family: Technology;
-}
-
-
-.refuel-display-container {
- margin-bottom: 10vh;
- padding: 30px 40px;
- background-image: url('../images/gas_refuel_display.png');
- background-repeat: no-repeat;
- background-position: center;
- width: 205px;
- height: 108px;
- background-size: 100%;
-}
-
-.refuel-display-info-container {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
-}
-
-.refuel-display-label {
- color: rgba(255, 255, 255, 0.6);
- font-size: 15px;
- font-style: normal;
- font-weight: 400;
- line-height: normal;
- letter-spacing: 0.5;
-}
-
-.refuel-display-value {
- color: #FFF;
- font-size: 25px;
- font-style: normal;
- font-weight: 400;
- line-height: normal;
- letter-spacing: 1;
-}
-
-.refuel-display-liters {
- color: #FFF;
- font-size: 19px;
-}
-
-/* Recharge display */
-.recharge-display-body {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: end;
- justify-content: center;
- z-index: 1000;
- font-family: Inter;
- color: white;
-}
-
-.recharge-display-container {
- margin-bottom: 10vh;
- background-image: url('../images/electric_charger_display.png');
- background-repeat: no-repeat;
- background-position: center;
- padding: 55px;
- width: 210px;
- height: 115px;
- background-size: 100%;
-}
-
-.recharge-display-title-container {
- display: flex;
- justify-content: center;
-}
-
-.recharge-display-title-container h3 {
- margin: 5px 0px 0px;
-}
-
-.recharge-display-battery-container {
- display: flex;
- gap: 10px;
- align-items: center;
-
- border-top: 1px solid #ffffff27;
- padding-top: 10px;
- margin-top: 10px;
-}
-
-:root {
- /* color */
- --gradient-color-red: linear-gradient(90deg,
- hsl( 7, 89%, 46%) 15%,
- hsl(11, 93%, 68%) 100%);
- --gradient-color-orange: linear-gradient(90deg,
- hsl( 22, 89%, 46%) 15%,
- hsl(54, 93%, 68%) 100%);
- --gradient-color-yellow: linear-gradient(90deg,
- hsl( 54, 89%, 46%) 15%,
- hsl(90, 93%, 68%) 100%);
- --gradient-color-green: linear-gradient(90deg,
- hsl( 92, 89%, 46%) 15%,
- hsl(90, 93%, 68%) 100%);
-}
-
-.recharge-display-battery-bar-container {
- position: relative;
- width: 100%;
- height: 10px;
- background-color: rgba(255, 255, 255, 0.13);
- backdrop-filter: blur(10px);
- border: 2px solid rgba(247, 240, 240, 0.1);
- border-radius: 3rem;
- justify-self: flex-start;
-
-}
-.recharge-display-battery-level {
- position: absolute;
- inset: 2px;
- border-radius: 3rem;
- overflow: hidden;
-}
-.recharge-display-battery-liquid {
- position: absolute;
- bottom: 0;
- top: 0;
- left: 0;
- width: 36px;
- background: var(--gradient-color-yellow);
- box-shadow: inset 12px 0 12px hsla(0, 0, 0, 0.15),
- inset -12px 0 12px hsla(0, 0, 0, 0.1);
- transition: 0.3s;
-
-}
-.recharge-display-battery-liquid::after {
- content: "";
- position: absolute;
- width: 8px;
- background: var(--gradient-color-yellow);
- box-shadow: inset 0px -3px 6px hsla(0, 0, 0, 0.2);
- top: 0;
- left: 0;
- margin: 0 auto;
- right: -4px;
- border-radius: 50%;
-}
-
-.recharge-display-remaining-time-container {
- display: flex;
- flex-direction: column;
- align-items: center;
-
- border-top: 1px solid #ffffff27;
- padding-top: 5px;
- margin-top: 10px;
-}
-
-.recharge-display-remaining-time-title {
- color: #FFF;
- font-family: Inter;
- font-size: 13px;
- font-style: normal;
- font-weight: 500;
- line-height: normal;
-}
-
-.recharge-display-remaining-time-value {
- color: #FFF;
- font-family: Inter;
- font-size: 16px;
- font-style: normal;
- font-weight: 700;
- line-height: normal;
-}
-
-/* ELECTRIC CHARGER structure */
-.electric-charger-container {
- display: flex;
- justify-content: center;
- align-items: flex-end;
- height: 100%;
- width: 100%;
- background: #00000070;
- font-family: Inter !important;
-}
-
-.electric-charger-elements-container {
- position: absolute;
- bottom: 440px;
- width: 540px;
- height: 535px;
- margin-right: 65px;
- display: grid;
- justify-items: center;
-}
-
-.electric-charger-button {
- padding: 10px;
- width: 285px;
- border-radius: 10px;
- background: rgba(255, 255, 255, 0.15);
- border: 0;
- transition: all 0.2s ease, cursor 0.2s ease;
-
- color: #FFF;
- text-align: center;
- font-family: Inter;
- font-size: 15px;
- font-style: normal;
- font-weight: 700;
- line-height: normal;
-}
-
-.electric-charger-button:hover {
- cursor: pointer;
- background: rgba(255, 255, 255, 0.24);
-}
-
-.electric-charger-title {
- color: #FFF;
- text-align: center;
- font-size: 40px;
- font-style: normal;
- font-weight: 900;
- line-height: normal;
- margin: 50px 0px
-}
-
-.electric-charger-subtitle {
- color: #FFF;
- text-align: center;
- font-size: 20px;
- font-style: normal;
- font-weight: 500;
- line-height: normal;
- margin: 5px 0px 40px 0px
-}
-
-.electric-charger-buttons-container {
- display: flex;
- gap: 15px;
- margin-bottom: 16px;
-}
-
-.electric-charger-return-container {
- position: absolute;
- top: 20px;
- left: 20px;
-}
-
-.electric-charger-return-container svg {
- height: 25px;
- fill: #ffffffa8;
-}
-
-.electric-charger-return-container svg:hover {
- fill: #ffffffcc;
- cursor: pointer;
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-
-/* RECHARGE TYPE */
-.electric-charger-type-container {
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-.electric-charger-type-input {
- display: none;
-}
-
-.electric-charger-type-input:not(:disabled) ~ .electric-charger-type-label {
- cursor: pointer;
-}
-
-.electric-charger-type-container .electric-charger-type-label {
- height: 150px;
- padding: 14px 13px 10px 13px;
-}
-
-.electric-charger-type-label {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-
- text-align: center;
- height: 125px;
- width: 115px;
- padding: 9px;
- border-radius: 10px;
-
- color: #FFF;
- font-size: 15px;
- font-style: normal;
- font-weight: 700;
- line-height: normal;
-
- background: rgba(255, 255, 255, 0.15);
- border: 1px solid rgba(255, 255, 255, 0);
-}
-
-.electric-charger-type-label:hover {
- cursor: pointer;
- background: rgba(255, 255, 255, 0.24);
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-
-/* Disable hover when input is disabled */
-input.electric-charger-type-input:disabled + .electric-charger-type-label {
- pointer-events: none; /* Disable hover and interaction */
- cursor: not-allowed; /* Optional: show not-allowed cursor */
- opacity: 0.5; /* Indicate visually that it's disabled */
-}
-
-.electric-charger-type-label h2 {
- margin: 15 0 5 0;
-}
-
-.electric-charger-type-input:checked + .electric-charger-type-label {
- border: 1px solid rgba(255, 255, 255, 0.35);
- background: rgba(255, 255, 255, 0.35);
-}
-
-.electric-charger-type-label-item-container {
- display: flex;
- gap: 5px;
-
- border-top: 1px solid #ffffff15;
- padding-top: 3px;
- margin-top: 3px;
-}
-
-.electric-charger-type-label-item-container svg {
- height: 15px;
- fill: #FFF;
-}
-
-.electric-charger-type-label-item-container span {
- font-size: 13px;
-}
-
-/* SELECT AMOUNT */
-.electric-charger-amount-container {
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-/* PAYMENT METHOD */
-.electric-charger-payment-container {
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-.electric-charger-amount-input-container {
- display: flex;
- gap: 10px;
-}
-
-.electric-charger-amount-input {
- display: flex;
- width: 125px;
- padding: 10px;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- gap: 7px;
- flex-shrink: 0;
- border-radius: 10px;
- border: 1px solid rgba(255, 255, 255, 0.25);
- background: rgba(255, 255, 255, 0.15);
-
- color: rgba(255, 255, 255, 0.6);
- text-align: center;
- font-size: 15px;
- font-style: normal;
- font-weight: 700;
- line-height: normal;
-}
-
-.electric-charger-amount-input::-webkit-outer-spin-button,
-.electric-charger-amount-input::-webkit-inner-spin-button {
--webkit-appearance: none;
-margin: 0;
-}
-
-.recharge-sub, .recharge-add {
- display: flex;
- width: 44px;
- height: 44px;
- padding: 10px;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- gap: 7px;
- flex-shrink: 0;
- border-radius: 10px;
- border: 1px solid rgba(255, 255, 255, 0.35);
- background: rgba(255, 255, 255, 0.35);
-
- color: #FFF;
- text-align: center;
- font-style: normal;
- font-weight: 400;
- line-height: normal;
-}
-
-.recharge-sub {
- font-size: 30px;
- padding-bottom: 15px;
-}
-
-.recharge-add {
- font-size: 25px;
-}
-
-.electric-amount-info-container {
- margin: 20px 0px 15px 0px;
-}
-
-.electric-amount-progress-container {
- display: flex;
- align-items: center;
- gap: 10px;
- width: 300px;
- margin-bottom: 5px;
-}
-
-.electric-time-to-recharge {
- margin-left: 10px;
- color: #FFF;
- font-size: 15px;
- font-style: normal;
- font-weight: 600;
- line-height: normal;
-}
-
-.electric-time-to-recharge > span {
- font-weight: 800;
-}
-
-/* Makes the texts not selectable */
-body {
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- background: transparent !important;
- user-select: none;
-}
-
-/* Modal */
-.modal {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.6);
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 1000;
-}
-
-.modal-content {
- padding: 20px;
- border-radius: 8px;
- text-align: center;
- width: 300px;
- box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2);
- position: relative;
-
- border-radius: 5px;
- border: 2px solid rgba(75, 75, 75, 0.50);
- background: rgba(0, 0, 0, 0.5);
- color: white;
- font-family: "Lexend";
- margin-bottom: 100px;
-}
-
-.close-button {
- position: absolute;
- top: 2px;
- right: 13px;
- font-size: 24px;
- font-weight: bold;
- color: #6a6a6a;
- cursor: pointer;
-}
-
-.modal-buttons {
- display: flex;
- justify-content: space-around;
- margin-top: 20px;
- gap: 15px;
-}
-
-.modal-button {
- color: white;
- padding: 10px 20px;
- border: none;
- cursor: pointer;
- font-size: 16px;
-
- border-radius: 5px;
- background: rgba(255, 255, 255, 0.12);
- font-family: "Lexend";
- font-style: normal;
- font-weight: 700;
- line-height: normal;
- transition: all 0.2s ease, cursor 0.2s ease;
-}
-
-.modal-button:hover {
- background-color: #135015;
-}
-
-.modal-button.cancel-button:hover {
- background-color: #501313;
-}
-
-/* Chart dialog */
-.chart-dialog {
- position: fixed;
- width: 450px;
- box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.3);
- z-index: 9999;
- border-radius: 8px;
- text-align: center;
- border: 2px solid rgba(45, 45, 45, 0.60);
- background: rgba(0, 0, 0, 0.7);
- color: white;
- font-family: "Lexend";
- flex-direction: column;
- overflow: hidden;
-}
-
-.chart-dialog .dialog-body {
- flex: 1;
- position: relative;
- overflow: hidden;
-}
-
-.chart-dialog .dialog-header, .chart-dialog .dialog-footer {
- padding: 10px;
- flex-shrink: 0;
- font-weight: bold;
- font-size: 15px;
-}
-
-.chart-dialog .dialog-header {
- cursor: move;
-}
-
-.chart-dialog .dialog-footer {
- display: flex;
- align-items: flex-end;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
-}
-
-.chart-dialog .dialog-footer-inputs {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- gap: 5px;
-}
-
-.chart-dialog .decrease-chart-recording,
-.chart-dialog .increase-chart-recording {
- color: inherit;
- font: inherit;
-
- background: #0000003d;
- border: 1px solid #a7a7a745;
- border-radius: 5px;
-
- width: 24px;
- height: 24px;
- text-align: center;
- padding: 0px;
- font-size: 14px;
- font-weight: 300;
-}
-
-.chart-dialog .increase-chart-recording {
- padding-bottom: 2px;
-}
-
-.chart-dialog .chart-recording-input-container {
- display: flex;
- align-items: center;
- gap: 5px;
-}
-
-.chart-dialog canvas {
- margin-bottom: 20px;
-}
-
-/* Resizable properties */
-.ui-resizable-e {
- cursor: e-resize;
- width: 7px;
- right: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-s {
- cursor: s-resize;
- height: 7px;
- width: 100%;
- bottom: -5px;
- left: 0;
-}
-.ui-resizable-se {
- width: 16px;
- height: 16px;
- bottom: 0;
- right: 0;
- cursor: se-resize;
- background: url('data:image/svg+xml;utf8,') no-repeat center center;
- background-size: 12px 12px;
- opacity: 0.5;
-}
-.ui-resizable-se:hover::after, .ui-resizable-se:hover {
- opacity: 0.8;
-}
-.ui-resizable-handle {
- position: absolute;
- font-size: 0.1px;
- display: block;
- -ms-touch-action: none;
- touch-action: none;
+@font-face {
+ font-family: 'Technology';
+ font-style: normal;
+ font-weight: normal;
+ src: url('../fonts/Technology.woff') format('woff');
+}
+
+body {
+ margin: 0;
+}
+
+/* PUMP structure */
+.gas-pump-container {
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ height: 100%;
+ width: 100%;
+ background: #00000070;
+}
+
+.gas-pump-elements-container {
+ position: absolute;
+ bottom: 69px;
+ width: 100%;
+ display: grid;
+ justify-items: center;
+ line-height: 18px;
+}
+
+.gas-pump-values-container {
+ display: grid;
+ grid-template-columns: 110px 274px 224.18px 186.52px 110px;
+ white-space: nowrap;
+}
+
+.digital-text {
+ color: #EBFEFF;
+ font-family: Technology;
+ font-size: 17px;
+ letter-spacing: 1.7px;
+ display: inline-block;
+}
+
+.digital-text-2 {
+ color: #EBFEFF;
+ text-align: center;
+ font-family: Technology;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+ letter-spacing: 1.5px;
+ display: inline-block;
+}
+
+.digital-text.dark {
+ color: #263D3D;
+}
+
+/* Side buttons */
+.controls-container {
+ display: grid;
+ justify-items: start;
+ align-items: center;
+ font-family: 'Lexend';
+}
+
+.controls-container > button {
+ width: 37px;
+ height: 37px;
+ border-radius: 100px;
+ border: 1px solid rgba(200, 200, 200, 0.15);
+ background: rgba(0, 0, 0, 0.4);
+ transition: all 0.2s ease, cursor 0.2s ease;
+
+ color: #FFF;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+
+ /* Align the text */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.controls-container > button:hover {
+ cursor: pointer;
+ background: rgba(50, 50, 50, 0.4);
+}
+
+/* Interactive buttons */
+.gas-pump-interactive-button {
+ position: absolute;
+ bottom: 520px;
+ left: 50%;
+ transform: translateX(140px);
+ border-radius: 100px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ background: rgb(255 255 255 / 9%);
+ display: inline-flex;
+ padding: 7px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.gas-pump-interactive-inner-button {
+ width: 38px;
+ height: 38px;
+ border-radius: 100px;
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ background: rgb(255 255 255 / 29%);
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+
+.gas-pump-interactive-button:hover {
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ background: rgb(255 255 255 / 6%);
+ cursor: pointer;
+}
+
+.gas-pump-interactive-button:hover .gas-pump-interactive-inner-button {
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ background: rgb(255 255 255 / 20%);
+}
+
+/* Center side of the PUMP */
+.quantity-input-container {
+ display: flex;
+ justify-content: center;
+ margin: 0px 15px 38px;
+}
+
+.quantity-input-container > input {
+ width: 68%;
+ padding: 0px 5px;
+ text-align: center;
+ border:none;
+ background-image:none;
+ background-color:transparent;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ outline: none;
+}
+
+/* Chrome, Safari, Edge, Opera */
+.quantity-input-container > input::-webkit-outer-spin-button,
+.quantity-input-container > input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+/* Firefox */
+.quantity-input-container > input[type=number] {
+ -moz-appearance: textfield;
+}
+
+.quantity-input-container > button {
+ color: #EBFEFF;
+ font-family: Technology;
+ font-weight: 700;
+ width: 31px;
+ height: 31px;
+ padding: 1px;
+
+ border: 2px solid #72697E;
+ background: #251825;
+
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+.quantity-input-container > button:hover {
+ cursor: pointer;
+ background: rgba(99, 105, 105, 0.15);
+}
+.quantity-input-container > .sub {
+ font-size: 25px;
+}
+.quantity-input-container > .add {
+ font-size: 17px;
+}
+
+.price-per-liter {
+ margin: 10px 30px 26px 15px;
+}
+
+.stock-values-container {
+ display: grid;
+ grid-template-columns: 50% 50%;
+}
+
+.stock-values-container > span {
+ margin: 0px 14px 13px;
+}
+
+/* Right side of the PUMP */
+.money-display-container {
+ padding: 22px 18px 0px 11px;
+ display: grid;
+ justify-items: start;
+}
+
+.bank-balance {
+ margin: 6px;
+}
+
+.cash-balance {
+ margin: 26px 6px 15px;
+}
+
+.confirm-button {
+ color: #263D3D;
+ font-family: "Lexend Zetta";
+ font-weight: 800;
+ letter-spacing: -2.2px;
+ width: 100%;
+ height: fit-content;
+ padding: 6px 6px;
+ font-size: 13px;
+ background: #909B9C;
+ border: solid 2px #697474;
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+
+.confirm-button:hover {
+ cursor: pointer;
+ background: #a3afb1;
+}
+
+/* Footer of the PUMP */
+.gas-pump-fuel-list-container {
+ display: grid;
+ grid-template-columns: 26% 26% 26% 22%;
+ margin-top: 22px;
+ height: 34px;
+ align-items: center;
+ width: 685px;
+}
+
+.fuel-type-button {
+ height: -webkit-fill-available;
+ background: #ffffff00;
+ border: none;
+ color: rgba(255, 255, 255, 0.45);
+ text-align: right;
+ font-family: Arial;
+ font-size: 15px;
+ font-weight: 700;
+ padding-right: 12px;
+ margin: 1px;
+ transition: all 0.1s ease, color 0.1s ease;
+}
+
+.fuel-type-button:hover {
+ cursor: pointer;
+}
+
+@keyframes pulseRegular {
+ 0% {
+ background-color: rgba(255, 255, 255, 0.15);
+ box-shadow: rgb(255 255 255 / 30%) 0px 0px 8px 2px, rgb(255 255 255 / 10%) 0px 0px 4px 2px;
+ }
+ 50% {
+ background-color: rgba(255, 255, 255, 0.35);
+ box-shadow: rgb(255 255 255 / 50%) 0px 0px 12px 4px, rgb(255 255 255 / 20%) 0px 0px 6px 3px;
+ }
+ 100% {
+ background-color: rgba(255, 255, 255, 0.15);
+ box-shadow: rgb(255 255 255 / 30%) 0px 0px 8px 2px, rgb(255 255 255 / 10%) 0px 0px 4px 2px;
+ }
+}
+
+@keyframes pulsePlus {
+ 0% {
+ background-color: rgba(0, 119, 255, 0.15);
+ box-shadow: rgba(0, 119, 255, 0.2) 0px 0px 8px 2px, rgba(0, 119, 255, 0.22) 0px 0px 4px 2px;
+ }
+ 50% {
+ background-color: rgba(0, 119, 255, 0.35);
+ box-shadow: rgba(0, 119, 255, 0.5) 0px 0px 12px 4px, rgba(0, 119, 255, 0.35) 0px 0px 6px 3px;
+ }
+ 100% {
+ background-color: rgba(0, 119, 255, 0.15);
+ box-shadow: rgba(0, 119, 255, 0.2) 0px 0px 8px 2px, rgba(0, 119, 255, 0.22) 0px 0px 4px 2px;
+ }
+}
+
+@keyframes pulsePremium {
+ 0% {
+ background-color: rgba(255, 0, 0, 0.15);
+ box-shadow: rgba(255, 0, 0, 0.2) 0px 0px 8px 2px, rgba(255, 0, 0, 0.22) 0px 0px 4px 2px;
+ }
+ 50% {
+ background-color: rgba(255, 0, 0, 0.35);
+ box-shadow: rgba(255, 0, 0, 0.5) 0px 0px 12px 4px, rgba(255, 0, 0, 0.35) 0px 0px 6px 3px;
+ }
+ 100% {
+ background-color: rgba(255, 0, 0, 0.15);
+ box-shadow: rgba(255, 0, 0, 0.2) 0px 0px 8px 2px, rgba(255, 0, 0, 0.22) 0px 0px 4px 2px;
+ }
+}
+
+@keyframes pulseDiesel {
+ 0% {
+ background-color: rgba(0, 165, 0, 0.15);
+ box-shadow: rgba(0, 165, 0, 0.2) 0px 0px 8px 2px, rgba(0, 165, 0, 0.20) 0px 0px 4px 2px;
+ }
+ 50% {
+ background-color: rgba(0, 165, 0, 0.35);
+ box-shadow: rgba(0, 165, 0, 0.5) 0px 0px 12px 4px, rgba(0, 165, 0, 0.30) 0px 0px 6px 3px;
+ }
+ 100% {
+ background-color: rgba(0, 165, 0, 0.15);
+ box-shadow: rgba(0, 165, 0, 0.2) 0px 0px 8px 2px, rgba(0, 165, 0, 0.20) 0px 0px 4px 2px;
+ }
+}
+
+.fuel-type-button.regular.selected,
+.fuel-type-button.regular:hover {
+ background: rgba(255, 255, 255, 0.15);
+ cursor: pointer;
+ animation: pulseRegular 3s infinite ease-in-out;
+}
+
+.fuel-type-button.plus.selected,
+.fuel-type-button.plus:hover {
+ background: rgba(0, 119, 255, 0.15);
+ cursor: pointer;
+ animation: pulsePlus 3s infinite ease-in-out;
+}
+
+.fuel-type-button.premium.selected,
+.fuel-type-button.premium:hover {
+ background: rgba(255, 0, 0, 0.15);
+ cursor: pointer;
+ animation: pulsePremium 3s infinite ease-in-out;
+}
+
+.fuel-type-button.diesel.selected,
+.fuel-type-button.diesel:hover {
+ background: rgba(0, 165, 0, 0.15);
+ cursor: pointer;
+ animation: pulseDiesel 3s infinite ease-in-out;
+}
+
+
+.fuel-type-button.regular {
+ color: rgba(0, 0, 0, 0.75);
+}
+
+/* Refuel display */
+.refuel-display-body {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: end;
+ justify-content: center;
+ z-index: 1000;
+ font-family: Technology;
+}
+
+
+.refuel-display-container {
+ margin-bottom: 10vh;
+ padding: 30px 40px;
+ background-image: url('../images/gas_refuel_display.png');
+ background-repeat: no-repeat;
+ background-position: center;
+ width: 205px;
+ height: 108px;
+ background-size: 100%;
+}
+
+.refuel-display-info-container {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+}
+
+.refuel-display-label {
+ color: rgba(255, 255, 255, 0.6);
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ letter-spacing: 0.5;
+}
+
+.refuel-display-value {
+ color: #FFF;
+ font-size: 25px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ letter-spacing: 1;
+}
+
+.refuel-display-liters {
+ color: #FFF;
+ font-size: 19px;
+}
+
+/* Recharge display */
+.recharge-display-body {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: end;
+ justify-content: center;
+ z-index: 1000;
+ font-family: Inter;
+ color: white;
+}
+
+.recharge-display-container {
+ margin-bottom: 10vh;
+ background-image: url('../images/electric_charger_display.png');
+ background-repeat: no-repeat;
+ background-position: center;
+ padding: 55px;
+ width: 210px;
+ height: 115px;
+ background-size: 100%;
+}
+
+.recharge-display-title-container {
+ display: flex;
+ justify-content: center;
+}
+
+.recharge-display-title-container h3 {
+ margin: 5px 0px 0px;
+}
+
+.recharge-display-battery-container {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+
+ border-top: 1px solid #ffffff27;
+ padding-top: 10px;
+ margin-top: 10px;
+}
+
+:root {
+ /* color */
+ --gradient-color-red: linear-gradient(90deg,
+ hsl( 7, 89%, 46%) 15%,
+ hsl(11, 93%, 68%) 100%);
+ --gradient-color-orange: linear-gradient(90deg,
+ hsl( 22, 89%, 46%) 15%,
+ hsl(54, 93%, 68%) 100%);
+ --gradient-color-yellow: linear-gradient(90deg,
+ hsl( 54, 89%, 46%) 15%,
+ hsl(90, 93%, 68%) 100%);
+ --gradient-color-green: linear-gradient(90deg,
+ hsl( 92, 89%, 46%) 15%,
+ hsl(90, 93%, 68%) 100%);
+}
+
+.recharge-display-battery-bar-container {
+ position: relative;
+ width: 100%;
+ height: 10px;
+ background-color: rgba(255, 255, 255, 0.13);
+ backdrop-filter: blur(10px);
+ border: 2px solid rgba(247, 240, 240, 0.1);
+ border-radius: 3rem;
+ justify-self: flex-start;
+
+}
+.recharge-display-battery-level {
+ position: absolute;
+ inset: 2px;
+ border-radius: 3rem;
+ overflow: hidden;
+}
+.recharge-display-battery-liquid {
+ position: absolute;
+ bottom: 0;
+ top: 0;
+ left: 0;
+ width: 36px;
+ background: var(--gradient-color-yellow);
+ box-shadow: inset 12px 0 12px hsla(0, 0, 0, 0.15),
+ inset -12px 0 12px hsla(0, 0, 0, 0.1);
+ transition: 0.3s;
+
+}
+.recharge-display-battery-liquid::after {
+ content: "";
+ position: absolute;
+ width: 8px;
+ background: var(--gradient-color-yellow);
+ box-shadow: inset 0px -3px 6px hsla(0, 0, 0, 0.2);
+ top: 0;
+ left: 0;
+ margin: 0 auto;
+ right: -4px;
+ border-radius: 50%;
+}
+
+.recharge-display-remaining-time-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ border-top: 1px solid #ffffff27;
+ padding-top: 5px;
+ margin-top: 10px;
+}
+
+.recharge-display-remaining-time-title {
+ color: #FFF;
+ font-family: Inter;
+ font-size: 13px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: normal;
+}
+
+.recharge-display-remaining-time-value {
+ color: #FFF;
+ font-family: Inter;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+}
+
+/* ELECTRIC CHARGER structure */
+.electric-charger-container {
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ height: 100%;
+ width: 100%;
+ background: #00000070;
+ font-family: Inter !important;
+}
+
+.electric-charger-elements-container {
+ position: absolute;
+ bottom: 440px;
+ width: 540px;
+ height: 535px;
+ margin-right: 65px;
+ display: grid;
+ justify-items: center;
+}
+
+.electric-charger-button {
+ padding: 10px;
+ width: 285px;
+ border-radius: 10px;
+ background: rgba(255, 255, 255, 0.15);
+ border: 0;
+ transition: all 0.2s ease, cursor 0.2s ease;
+
+ color: #FFF;
+ text-align: center;
+ font-family: Inter;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+}
+
+.electric-charger-button:hover {
+ cursor: pointer;
+ background: rgba(255, 255, 255, 0.24);
+}
+
+.electric-charger-title {
+ color: #FFF;
+ text-align: center;
+ font-size: 40px;
+ font-style: normal;
+ font-weight: 900;
+ line-height: normal;
+ margin: 50px 0px
+}
+
+.electric-charger-subtitle {
+ color: #FFF;
+ text-align: center;
+ font-size: 20px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: normal;
+ margin: 5px 0px 40px 0px
+}
+
+.electric-charger-buttons-container {
+ display: flex;
+ gap: 15px;
+ margin-bottom: 16px;
+}
+
+.electric-charger-return-container {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+}
+
+.electric-charger-return-container svg {
+ height: 25px;
+ fill: #ffffffa8;
+}
+
+.electric-charger-return-container svg:hover {
+ fill: #ffffffcc;
+ cursor: pointer;
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+
+/* RECHARGE TYPE */
+.electric-charger-type-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.electric-charger-type-input {
+ display: none;
+}
+
+.electric-charger-type-input:not(:disabled) ~ .electric-charger-type-label {
+ cursor: pointer;
+}
+
+.electric-charger-type-container .electric-charger-type-label {
+ height: 150px;
+ padding: 14px 13px 10px 13px;
+}
+
+.electric-charger-type-label {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+
+ text-align: center;
+ height: 125px;
+ width: 115px;
+ padding: 9px;
+ border-radius: 10px;
+
+ color: #FFF;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+
+ background: rgba(255, 255, 255, 0.15);
+ border: 1px solid rgba(255, 255, 255, 0);
+}
+
+.electric-charger-type-label:hover {
+ cursor: pointer;
+ background: rgba(255, 255, 255, 0.24);
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+
+/* Disable hover when input is disabled */
+input.electric-charger-type-input:disabled + .electric-charger-type-label {
+ pointer-events: none; /* Disable hover and interaction */
+ cursor: not-allowed; /* Optional: show not-allowed cursor */
+ opacity: 0.5; /* Indicate visually that it's disabled */
+}
+
+.electric-charger-type-label h2 {
+ margin: 15 0 5 0;
+}
+
+.electric-charger-type-input:checked + .electric-charger-type-label {
+ border: 1px solid rgba(255, 255, 255, 0.35);
+ background: rgba(255, 255, 255, 0.35);
+}
+
+.electric-charger-type-label-item-container {
+ display: flex;
+ gap: 5px;
+
+ border-top: 1px solid #ffffff15;
+ padding-top: 3px;
+ margin-top: 3px;
+}
+
+.electric-charger-type-label-item-container svg {
+ height: 15px;
+ fill: #FFF;
+}
+
+.electric-charger-type-label-item-container span {
+ font-size: 13px;
+}
+
+/* SELECT AMOUNT */
+.electric-charger-amount-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+/* PAYMENT METHOD */
+.electric-charger-payment-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.electric-charger-amount-input-container {
+ display: flex;
+ gap: 10px;
+}
+
+.electric-charger-amount-input {
+ display: flex;
+ width: 125px;
+ padding: 10px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 7px;
+ flex-shrink: 0;
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ background: rgba(255, 255, 255, 0.15);
+
+ color: rgba(255, 255, 255, 0.6);
+ text-align: center;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+}
+
+.electric-charger-amount-input::-webkit-outer-spin-button,
+.electric-charger-amount-input::-webkit-inner-spin-button {
+-webkit-appearance: none;
+margin: 0;
+}
+
+.recharge-sub, .recharge-add {
+ display: flex;
+ width: 44px;
+ height: 44px;
+ padding: 10px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 7px;
+ flex-shrink: 0;
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.35);
+ background: rgba(255, 255, 255, 0.35);
+
+ color: #FFF;
+ text-align: center;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+}
+
+.recharge-sub {
+ font-size: 30px;
+ padding-bottom: 15px;
+}
+
+.recharge-add {
+ font-size: 25px;
+}
+
+.electric-amount-info-container {
+ margin: 20px 0px 15px 0px;
+}
+
+.electric-amount-progress-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ width: 300px;
+ margin-bottom: 5px;
+}
+
+.electric-time-to-recharge {
+ margin-left: 10px;
+ color: #FFF;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+}
+
+.electric-time-to-recharge > span {
+ font-weight: 800;
+}
+
+/* Makes the texts not selectable */
+body {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ background: transparent !important;
+ user-select: none;
+}
+
+/* Modal */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+}
+
+.modal-content {
+ padding: 20px;
+ border-radius: 8px;
+ text-align: center;
+ width: 300px;
+ box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2);
+ position: relative;
+
+ border-radius: 5px;
+ border: 2px solid rgba(75, 75, 75, 0.50);
+ background: rgba(0, 0, 0, 0.5);
+ color: white;
+ font-family: "Lexend";
+ margin-bottom: 100px;
+}
+
+.close-button {
+ position: absolute;
+ top: 2px;
+ right: 13px;
+ font-size: 24px;
+ font-weight: bold;
+ color: #6a6a6a;
+ cursor: pointer;
+}
+
+.modal-buttons {
+ display: flex;
+ justify-content: space-around;
+ margin-top: 20px;
+ gap: 15px;
+}
+
+.modal-button {
+ color: white;
+ padding: 10px 20px;
+ border: none;
+ cursor: pointer;
+ font-size: 16px;
+
+ border-radius: 5px;
+ background: rgba(255, 255, 255, 0.12);
+ font-family: "Lexend";
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+ transition: all 0.2s ease, cursor 0.2s ease;
+}
+
+.modal-button:hover {
+ background-color: #135015;
+}
+
+.modal-button.cancel-button:hover {
+ background-color: #501313;
+}
+
+/* Chart dialog */
+.chart-dialog {
+ position: fixed;
+ width: 450px;
+ box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.3);
+ z-index: 9999;
+ border-radius: 8px;
+ text-align: center;
+ border: 2px solid rgba(45, 45, 45, 0.60);
+ background: rgba(0, 0, 0, 0.7);
+ color: white;
+ font-family: "Lexend";
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.chart-dialog .dialog-body {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+}
+
+.chart-dialog .dialog-header, .chart-dialog .dialog-footer {
+ padding: 10px;
+ flex-shrink: 0;
+ font-weight: bold;
+ font-size: 15px;
+}
+
+.chart-dialog .dialog-header {
+ cursor: move;
+}
+
+.chart-dialog .dialog-footer {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ font-size: 13px;
+ font-weight: 400;
+}
+
+.chart-dialog .dialog-footer-inputs {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 5px;
+}
+
+.chart-dialog .decrease-chart-recording,
+.chart-dialog .increase-chart-recording {
+ color: inherit;
+ font: inherit;
+
+ background: #0000003d;
+ border: 1px solid #a7a7a745;
+ border-radius: 5px;
+
+ width: 24px;
+ height: 24px;
+ text-align: center;
+ padding: 0px;
+ font-size: 14px;
+ font-weight: 300;
+}
+
+.chart-dialog .increase-chart-recording {
+ padding-bottom: 2px;
+}
+
+.chart-dialog .chart-recording-input-container {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+}
+
+.chart-dialog canvas {
+ margin-bottom: 20px;
+}
+
+/* Resizable properties */
+.ui-resizable-e {
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+}
+.ui-resizable-s {
+ cursor: s-resize;
+ height: 7px;
+ width: 100%;
+ bottom: -5px;
+ left: 0;
+}
+.ui-resizable-se {
+ width: 16px;
+ height: 16px;
+ bottom: 0;
+ right: 0;
+ cursor: se-resize;
+ background: url('data:image/svg+xml;utf8,') no-repeat center center;
+ background-size: 12px 12px;
+ opacity: 0.5;
+}
+.ui-resizable-se:hover::after, .ui-resizable-se:hover {
+ opacity: 0.8;
+}
+.ui-resizable-handle {
+ position: absolute;
+ font-size: 0.1px;
+ display: block;
+ -ms-touch-action: none;
+ touch-action: none;
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/de.js b/resources/[carscripts]/lc_fuel/nui/lang/de.js
index 32239732d..459e3cf2a 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/de.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/de.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["de"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "Bestätigen",
- vehicleFuelTooltip: "Aktueller Kraftstoff / Tankkapazität",
- fuelTypes: {
- regular: "Regulär",
- plus: "Plus",
- premium: "Premium",
- diesel: "Diesel",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "Autotank",
- remaining: "Übrig",
- },
- confirmRefuelModal: {
- title: "Bestätigen Sie „Tanken“.",
- description: "Sie kaufen {0}L {1} Kraftstoff für {2}.",
- paymentBank: "Bezahlen Sie mit der Bank",
- paymentCash: "Bezahlen Sie mit Bargeld",
- },
- confirmBuyJerryCanModal: {
- title: "Kauf Bestätigen",
- paymentBank: "Bezahlen Sie mit der Bank",
- paymentCash: "Bezahlen Sie mit Bargeld",
- },
- confirmFuelChangeModal: {
- title: "Kraftstoffe können nicht gemischt werden",
- description: "⚠️ Kraftstoffe können nicht gemischt werden",
- },
- electricInterface: {
- chargerType: {
- title: "LADEGERÄTETYP",
- fast: {
- title: "SCHNELL",
- power: "220kW",
- },
- normal: {
- title: "NORMAL",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "BETRAG WÄHLEN",
- typeSelected: "{0} AUSGEWÄHLT",
- placeholder: "Menge",
- timeToRechargeText: "Zeit zum Aufladen:",
- timeToRechargeValue: "{0} min {1} sec",
- },
- chargerPayment: {
- title: "Bezahlmethode",
- money: "Bar",
- bank: "Karte",
- payButton: "Bezahlen {0}",
- },
- continueButton: "Bestätigen",
- outOfStock: "Ausverkauft",
- },
- rechargerDisplay: {
- title: "AUFLADEN...",
- remainingTimeText: "VERBLEIBENDE ZEIT",
- remainingTimeValue: "{0} min {1} sek",
- },
- fuelConsumptionChart: {
- title: "Kraftstoffverbrauchsdiagramm",
- chartLabels: {
- fuel: "Kraftstoff (%)",
- speed: "Geschwindigkeit (km/h)",
- consumption: "Verbrauch (L/s)",
- shortSeconds: "{0}s",
- },
- footer: {
- focus: "F3 zum Fokussieren umschalten",
- toggleRecording: "Aufnahme umschalten",
- recordsLength: "Verlaufslänge ({0}s)",
- },
- },
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["de"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "Bestätigen",
+ vehicleFuelTooltip: "Aktueller Kraftstoff / Tankkapazität",
+ fuelTypes: {
+ regular: "Regulär",
+ plus: "Plus",
+ premium: "Premium",
+ diesel: "Diesel",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "Autotank",
+ remaining: "Übrig",
+ },
+ confirmRefuelModal: {
+ title: "Bestätigen Sie „Tanken“.",
+ description: "Sie kaufen {0}L {1} Kraftstoff für {2}.",
+ paymentBank: "Bezahlen Sie mit der Bank",
+ paymentCash: "Bezahlen Sie mit Bargeld",
+ },
+ confirmBuyJerryCanModal: {
+ title: "Kauf Bestätigen",
+ paymentBank: "Bezahlen Sie mit der Bank",
+ paymentCash: "Bezahlen Sie mit Bargeld",
+ },
+ confirmFuelChangeModal: {
+ title: "Kraftstoffe können nicht gemischt werden",
+ description: "⚠️ Kraftstoffe können nicht gemischt werden",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "LADEGERÄTETYP",
+ fast: {
+ title: "SCHNELL",
+ power: "220kW",
+ },
+ normal: {
+ title: "NORMAL",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "BETRAG WÄHLEN",
+ typeSelected: "{0} AUSGEWÄHLT",
+ placeholder: "Menge",
+ timeToRechargeText: "Zeit zum Aufladen:",
+ timeToRechargeValue: "{0} min {1} sec",
+ },
+ chargerPayment: {
+ title: "Bezahlmethode",
+ money: "Bar",
+ bank: "Karte",
+ payButton: "Bezahlen {0}",
+ },
+ continueButton: "Bestätigen",
+ outOfStock: "Ausverkauft",
+ },
+ rechargerDisplay: {
+ title: "AUFLADEN...",
+ remainingTimeText: "VERBLEIBENDE ZEIT",
+ remainingTimeValue: "{0} min {1} sek",
+ },
+ fuelConsumptionChart: {
+ title: "Kraftstoffverbrauchsdiagramm",
+ chartLabels: {
+ fuel: "Kraftstoff (%)",
+ speed: "Geschwindigkeit (km/h)",
+ consumption: "Verbrauch (L/s)",
+ shortSeconds: "{0}s",
+ },
+ footer: {
+ focus: "F3 zum Fokussieren umschalten",
+ toggleRecording: "Aufnahme umschalten",
+ recordsLength: "Verlaufslänge ({0}s)",
+ },
+ },
};
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/en.js b/resources/[carscripts]/lc_fuel/nui/lang/en.js
index 044bd6818..9e1ff6bb4 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/en.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/en.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["en"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "CONFIRM",
- vehicleFuelTooltip: "Current Fuel / Tank Capacity",
- fuelTypes: {
- regular: "Regular",
- plus: "Plus",
- premium: "Premium",
- diesel: "Diesel",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "Car Tank",
- remaining: "Remaining",
- },
- confirmRefuelModal: {
- title: "Confirm Refuel",
- description: "You are purchasing {0}L of {1} fuel for {2}.",
- paymentBank: "Pay with bank",
- paymentCash: "Pay with cash",
- },
- confirmBuyJerryCanModal: {
- title: "Confirm Purchase",
- paymentBank: "Pay with bank",
- paymentCash: "Pay with cash",
- },
- confirmFuelChangeModal: {
- title: "Fuels cannot be mixed",
- description: "⚠️ To change the fuel type in your vehicle, the tank will be emptied.",
- },
- electricInterface: {
- chargerType: {
- title: "CHARGER TYPE",
- fast: {
- title: "FAST",
- power: "220kW",
- },
- normal: {
- title: "NORMAL",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "SELECT AMOUNT",
- typeSelected: "{0} CHARGER",
- placeholder: "Amount",
- timeToRechargeText: "Time to recharge:",
- timeToRechargeValue: "{0} min {1} sec",
- },
- chargerPayment: {
- title: "PAYMENT METHOD",
- money: "MONEY",
- bank: "BANK",
- payButton: "PAY {0}",
- },
- continueButton: "CONTINUE",
- outOfStock: "Out of stock",
- },
- rechargerDisplay: {
- title: "CHARGING...",
- remainingTimeText: "REMAINING TIME",
- remainingTimeValue: "{0} min {1} sec",
- },
- fuelConsumptionChart: {
- title: "Fuel consumption chart",
- chartLabels: {
- fuel: "Fuel (%)",
- speed: "Speed (km/h)",
- consumption: "Consumption (L/s)",
- shortSeconds: "{0}s",
- },
- footer: {
- focus: "F3 to toggle focus",
- toggleRecording: "Toggle Recording",
- recordsLength: "History Length ({0}s)",
- },
- },
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["en"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "CONFIRM",
+ vehicleFuelTooltip: "Current Fuel / Tank Capacity",
+ fuelTypes: {
+ regular: "Regular",
+ plus: "Plus",
+ premium: "Premium",
+ diesel: "Diesel",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "Car Tank",
+ remaining: "Remaining",
+ },
+ confirmRefuelModal: {
+ title: "Confirm Refuel",
+ description: "You are purchasing {0}L of {1} fuel for {2}.",
+ paymentBank: "Pay with bank",
+ paymentCash: "Pay with cash",
+ },
+ confirmBuyJerryCanModal: {
+ title: "Confirm Purchase",
+ paymentBank: "Pay with bank",
+ paymentCash: "Pay with cash",
+ },
+ confirmFuelChangeModal: {
+ title: "Fuels cannot be mixed",
+ description: "⚠️ To change the fuel type in your vehicle, the tank will be emptied.",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "CHARGER TYPE",
+ fast: {
+ title: "FAST",
+ power: "220kW",
+ },
+ normal: {
+ title: "NORMAL",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "SELECT AMOUNT",
+ typeSelected: "{0} CHARGER",
+ placeholder: "Amount",
+ timeToRechargeText: "Time to recharge:",
+ timeToRechargeValue: "{0} min {1} sec",
+ },
+ chargerPayment: {
+ title: "PAYMENT METHOD",
+ money: "MONEY",
+ bank: "BANK",
+ payButton: "PAY {0}",
+ },
+ continueButton: "CONTINUE",
+ outOfStock: "Out of stock",
+ },
+ rechargerDisplay: {
+ title: "CHARGING...",
+ remainingTimeText: "REMAINING TIME",
+ remainingTimeValue: "{0} min {1} sec",
+ },
+ fuelConsumptionChart: {
+ title: "Fuel consumption chart",
+ chartLabels: {
+ fuel: "Fuel (%)",
+ speed: "Speed (km/h)",
+ consumption: "Consumption (L/s)",
+ shortSeconds: "{0}s",
+ },
+ footer: {
+ focus: "F3 to toggle focus",
+ toggleRecording: "Toggle Recording",
+ recordsLength: "History Length ({0}s)",
+ },
+ },
};
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/es.js b/resources/[carscripts]/lc_fuel/nui/lang/es.js
index 01b903136..2fd9f9bad 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/es.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/es.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["es"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "CONFIRMAR",
- vehicleFuelTooltip: "Combustible actual / Capacidad del tanque",
- fuelTypes: {
- regular: "Sin plomo",
- plus: "Plus",
- premium: "Premium",
- diesel: "Diésel",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "Depósito del coche",
- remaining: "Restante",
- },
- confirmRefuelModal: {
- title: "Confirmar Repostaje",
- description: "Estás comprando {0}L de combustible {1} por {2}.",
- paymentBank: "Pagar con el banco",
- paymentCash: "Pagar en efectivo",
- },
- confirmBuyJerryCanModal: {
- title: "Confirmar Compra",
- paymentBank: "Pagar con el banco",
- paymentCash: "Pagar en efectivo",
- },
- confirmFuelChangeModal: {
- title: "No se pueden mezclar combustibles",
- description: "⚠️ Para cambiar el tipo de combustible en tu vehículo, el depósito se vaciará.",
- },
- electricInterface: {
- chargerType: {
- title: "TIPO DE CARGADOR",
- fast: {
- title: "RÁPIDO",
- power: "220kW",
- },
- normal: {
- title: "NORMAL",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "SELECCIONAR CANTIDAD",
- typeSelected: "CARGADOR {0}",
- placeholder: "Cantidad",
- timeToRechargeText: "Tiempo de recarga:",
- timeToRechargeValue: "{0} min {1} seg",
- },
- chargerPayment: {
- title: "MÉTODO DE PAGO",
- money: "EFECTIVO",
- bank: "BANCO",
- payButton: "PAGAR {0}",
- },
- continueButton: "CONTINUAR",
- outOfStock: "Sin stock",
- },
- rechargerDisplay: {
- title: "CARGANDO...",
- remainingTimeText: "TIEMPO RESTANTE",
- remainingTimeValue: "{0} min {1} seg",
- },
- fuelConsumptionChart: {
- title: "Gráfico de consumo de combustible",
- chartLabels: {
- fuel: "Combustible (%)",
- speed: "Velocidad (km/h)",
- consumption: "Consumo (L/s)",
- shortSeconds: "{0}s",
- },
- footer: {
- focus: "F3 para alternar enfoque",
- toggleRecording: "Alternar grabación",
- recordsLength: "Duración del historial ({0}s)",
- },
- },
-};
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["es"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "CONFIRMAR",
+ vehicleFuelTooltip: "Combustible actual / Capacidad del tanque",
+ fuelTypes: {
+ regular: "Sin plomo",
+ plus: "Plus",
+ premium: "Premium",
+ diesel: "Diésel",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "Depósito del coche",
+ remaining: "Restante",
+ },
+ confirmRefuelModal: {
+ title: "Confirmar Repostaje",
+ description: "Estás comprando {0}L de combustible {1} por {2}.",
+ paymentBank: "Pagar con el banco",
+ paymentCash: "Pagar en efectivo",
+ },
+ confirmBuyJerryCanModal: {
+ title: "Confirmar Compra",
+ paymentBank: "Pagar con el banco",
+ paymentCash: "Pagar en efectivo",
+ },
+ confirmFuelChangeModal: {
+ title: "No se pueden mezclar combustibles",
+ description: "⚠️ Para cambiar el tipo de combustible en tu vehículo, el depósito se vaciará.",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "TIPO DE CARGADOR",
+ fast: {
+ title: "RÁPIDO",
+ power: "220kW",
+ },
+ normal: {
+ title: "NORMAL",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "SELECCIONAR CANTIDAD",
+ typeSelected: "CARGADOR {0}",
+ placeholder: "Cantidad",
+ timeToRechargeText: "Tiempo de recarga:",
+ timeToRechargeValue: "{0} min {1} seg",
+ },
+ chargerPayment: {
+ title: "MÉTODO DE PAGO",
+ money: "EFECTIVO",
+ bank: "BANCO",
+ payButton: "PAGAR {0}",
+ },
+ continueButton: "CONTINUAR",
+ outOfStock: "Sin stock",
+ },
+ rechargerDisplay: {
+ title: "CARGANDO...",
+ remainingTimeText: "TIEMPO RESTANTE",
+ remainingTimeValue: "{0} min {1} seg",
+ },
+ fuelConsumptionChart: {
+ title: "Gráfico de consumo de combustible",
+ chartLabels: {
+ fuel: "Combustible (%)",
+ speed: "Velocidad (km/h)",
+ consumption: "Consumo (L/s)",
+ shortSeconds: "{0}s",
+ },
+ footer: {
+ focus: "F3 para alternar enfoque",
+ toggleRecording: "Alternar grabación",
+ recordsLength: "Duración del historial ({0}s)",
+ },
+ },
+};
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/fr.js b/resources/[carscripts]/lc_fuel/nui/lang/fr.js
index 63eb492c8..5c4c10e1c 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/fr.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/fr.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["fr"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "CONFIRMER",
- vehicleFuelTooltip: "Carburant actuel / Capacité du réservoir",
- fuelTypes: {
- regular: "Ordinaire",
- plus: "Plus",
- premium: "Premium",
- diesel: "Diesel",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "Réservoir",
- remaining: "Restant",
- },
- confirmRefuelModal: {
- title: "Confirmer le ravitaillement",
- description: "Vous achetez {0} L de carburant {1} pour {2}.",
- paymentBank: "Payer avec la banque",
- paymentCash: "Payer en espèces",
- },
- confirmBuyJerryCanModal: {
- title: "Confirmer l'achat",
- paymentBank: "Payer avec la banque",
- paymentCash: "Payer en espèces",
- },
- confirmFuelChangeModal: {
- title: "Les carburants ne peuvent pas être mélangés",
- description: "⚠️ Pour changer le type de carburant dans votre véhicule, le réservoir sera vidé.",
- },
- electricInterface: {
- chargerType: {
- title: "TYPE DE CHARGEUR",
- fast: {
- title: "RAPIDE",
- power: "220kW",
- },
- normal: {
- title: "NORMAL",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "SÉLECTIONNER LA QUANTITÉ",
- typeSelected: "{0} CHARGEUR",
- placeholder: "Quantité",
- timeToRechargeText: "Temps pour recharger :",
- timeToRechargeValue: "{0} min {1} sec",
- },
- chargerPayment: {
- title: "MODE DE PAIEMENT",
- money: "ESPÈCES",
- bank: "BANQUE",
- payButton: "PAYER {0}",
- },
- continueButton: "CONTINUER",
- outOfStock: "Rupture de stock",
- },
- rechargerDisplay: {
- title: "CHARGE EN COURS...",
- remainingTimeText: "TEMPS RESTANT",
- remainingTimeValue: "{0} min {1} sec",
- },
- fuelConsumptionChart: {
- title: "Graphique de consommation de carburant",
- chartLabels: {
- fuel: "Carburant (%)",
- speed: "Vitesse (km/h)",
- consumption: "Consommation (L/s)",
- shortSeconds: "{0}s",
- },
- footer: {
- focus: "F3 pour basculer le focus",
- toggleRecording: "Activer/Désactiver l’enregistrement",
- recordsLength: "Durée de l’historique ({0}s)",
- },
- },
-};
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["fr"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "CONFIRMER",
+ vehicleFuelTooltip: "Carburant actuel / Capacité du réservoir",
+ fuelTypes: {
+ regular: "Ordinaire",
+ plus: "Plus",
+ premium: "Premium",
+ diesel: "Diesel",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "Réservoir",
+ remaining: "Restant",
+ },
+ confirmRefuelModal: {
+ title: "Confirmer le ravitaillement",
+ description: "Vous achetez {0} L de carburant {1} pour {2}.",
+ paymentBank: "Payer avec la banque",
+ paymentCash: "Payer en espèces",
+ },
+ confirmBuyJerryCanModal: {
+ title: "Confirmer l'achat",
+ paymentBank: "Payer avec la banque",
+ paymentCash: "Payer en espèces",
+ },
+ confirmFuelChangeModal: {
+ title: "Les carburants ne peuvent pas être mélangés",
+ description: "⚠️ Pour changer le type de carburant dans votre véhicule, le réservoir sera vidé.",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "TYPE DE CHARGEUR",
+ fast: {
+ title: "RAPIDE",
+ power: "220kW",
+ },
+ normal: {
+ title: "NORMAL",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "SÉLECTIONNER LA QUANTITÉ",
+ typeSelected: "{0} CHARGEUR",
+ placeholder: "Quantité",
+ timeToRechargeText: "Temps pour recharger :",
+ timeToRechargeValue: "{0} min {1} sec",
+ },
+ chargerPayment: {
+ title: "MODE DE PAIEMENT",
+ money: "ESPÈCES",
+ bank: "BANQUE",
+ payButton: "PAYER {0}",
+ },
+ continueButton: "CONTINUER",
+ outOfStock: "Rupture de stock",
+ },
+ rechargerDisplay: {
+ title: "CHARGE EN COURS...",
+ remainingTimeText: "TEMPS RESTANT",
+ remainingTimeValue: "{0} min {1} sec",
+ },
+ fuelConsumptionChart: {
+ title: "Graphique de consommation de carburant",
+ chartLabels: {
+ fuel: "Carburant (%)",
+ speed: "Vitesse (km/h)",
+ consumption: "Consommation (L/s)",
+ shortSeconds: "{0}s",
+ },
+ footer: {
+ focus: "F3 pour basculer le focus",
+ toggleRecording: "Activer/Désactiver l’enregistrement",
+ recordsLength: "Durée de l’historique ({0}s)",
+ },
+ },
+};
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/ja.js b/resources/[carscripts]/lc_fuel/nui/lang/ja.js
index d940a0bb0..3099e52d2 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/ja.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/ja.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["ja"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "確認",
- vehicleFuelTooltip: "現在の燃料 / タンク容量",
- fuelTypes: {
- regular: "レギュラー",
- plus: "プラス",
- premium: "プレミアム",
- diesel: "ディーゼル",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "自動車タンク",
- remaining: "残り",
- },
- confirmRefuelModal: {
- title: "給油の確認",
- description: "{0}Lの{1}を{2}で購入します。",
- paymentBank: "銀行で支払う",
- paymentCash: "現金で支払う",
- },
- confirmBuyJerryCanModal: {
- title: "購入を確認する",
- paymentBank: "銀行で支払う",
- paymentCash: "現金で支払う",
- },
- confirmFuelChangeModal: {
- title: "燃料の混合はできません",
- description: "⚠️ 燃料の種類を変更する場合はタンクを空にしてください。",
- },
- electricInterface: {
- chargerType: {
- title: "チャージャータイプ",
- fast: {
- title: "高速",
- power: "220kW",
- },
- normal: {
- title: "普通",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "金額選択",
- typeSelected: "{0}チャージャー",
- placeholder: "金額",
- timeToRechargeText: "充電時間:",
- timeToRechargeValue: "{0} 分 {1} 秒",
- },
- chargerPayment: {
- title: "支払い方法",
- money: "現金",
- bank: "銀行",
- payButton: "{0}で支払う",
- },
- continueButton: "決定",
- outOfStock: "在庫切れ",
- },
- rechargerDisplay: {
- title: "充電中・・・",
- remainingTimeText: "残り時間",
- remainingTimeValue: "{0} 分 {1} 秒",
- },
- fuelConsumptionChart: {
- title: "燃料消費チャート",
- chartLabels: {
- fuel: "燃料 (%)",
- speed: "速度 (km/h)",
- consumption: "消費量 (L/s)",
- shortSeconds: "{0}秒",
- },
- footer: {
- focus: "F3でフォーカス切替",
- toggleRecording: "記録の切り替え",
- recordsLength: "履歴の長さ ({0}秒)",
- },
- },
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["ja"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "確認",
+ vehicleFuelTooltip: "現在の燃料 / タンク容量",
+ fuelTypes: {
+ regular: "レギュラー",
+ plus: "プラス",
+ premium: "プレミアム",
+ diesel: "ディーゼル",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "自動車タンク",
+ remaining: "残り",
+ },
+ confirmRefuelModal: {
+ title: "給油の確認",
+ description: "{0}Lの{1}を{2}で購入します。",
+ paymentBank: "銀行で支払う",
+ paymentCash: "現金で支払う",
+ },
+ confirmBuyJerryCanModal: {
+ title: "購入を確認する",
+ paymentBank: "銀行で支払う",
+ paymentCash: "現金で支払う",
+ },
+ confirmFuelChangeModal: {
+ title: "燃料の混合はできません",
+ description: "⚠️ 燃料の種類を変更する場合はタンクを空にしてください。",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "チャージャータイプ",
+ fast: {
+ title: "高速",
+ power: "220kW",
+ },
+ normal: {
+ title: "普通",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "金額選択",
+ typeSelected: "{0}チャージャー",
+ placeholder: "金額",
+ timeToRechargeText: "充電時間:",
+ timeToRechargeValue: "{0} 分 {1} 秒",
+ },
+ chargerPayment: {
+ title: "支払い方法",
+ money: "現金",
+ bank: "銀行",
+ payButton: "{0}で支払う",
+ },
+ continueButton: "決定",
+ outOfStock: "在庫切れ",
+ },
+ rechargerDisplay: {
+ title: "充電中・・・",
+ remainingTimeText: "残り時間",
+ remainingTimeValue: "{0} 分 {1} 秒",
+ },
+ fuelConsumptionChart: {
+ title: "燃料消費チャート",
+ chartLabels: {
+ fuel: "燃料 (%)",
+ speed: "速度 (km/h)",
+ consumption: "消費量 (L/s)",
+ shortSeconds: "{0}秒",
+ },
+ footer: {
+ focus: "F3でフォーカス切替",
+ toggleRecording: "記録の切り替え",
+ recordsLength: "履歴の長さ ({0}秒)",
+ },
+ },
};
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/tr.js b/resources/[carscripts]/lc_fuel/nui/lang/tr.js
index 16dd4a844..c65c3a431 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/tr.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/tr.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["tr"] = {
- pumpInterface: {
- stationStock: "{0} L",
- vehicleFuel: "{0} L",
- confirm: "ONAYLA",
- vehicleFuelTooltip: "Mevcut Yakıt / Depo Kapasitesi",
- fuelTypes: {
- regular: "Normal",
- plus: "Plus",
- premium: "Premium",
- diesel: "Dizel",
- },
- },
- pumpRefuelDisplay: {
- liters: "L",
- carTank: "Araç Deposu",
- remaining: "Kalan",
- },
- confirmRefuelModal: {
- title: "Yakıt Alımını Onayla",
- description: "{0}L {1} yakıtı {2} karşılığında satın alıyorsunuz.",
- paymentBank: "Banka ile öde",
- paymentCash: "Nakit ile öde",
- },
- confirmBuyJerryCanModal: {
- title: "Satın Alımı Onayla",
- paymentBank: "Banka ile öde",
- paymentCash: "Nakit ile öde",
- },
- confirmFuelChangeModal: {
- title: "Yakıtlar Karıştırılamaz",
- description: "⚠️ Araçtaki yakıt türünü değiştirmek için depo boşaltılacaktır.",
- },
- electricInterface: {
- chargerType: {
- title: "ŞARJ CİHAZI TÜRÜ",
- fast: {
- title: "HIZLI",
- power: "220kW",
- },
- normal: {
- title: "NORMAL",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "MİKTAR SEÇİN",
- typeSelected: "{0} ŞARJ CİHAZI",
- placeholder: "Miktar",
- timeToRechargeText: "Şarj süresi:",
- timeToRechargeValue: "{0} dk {1} sn",
- },
- chargerPayment: {
- title: "ÖDEME YÖNTEMİ",
- money: "NAKİT",
- bank: "BANKA",
- payButton: "{0} ÖDE",
- },
- continueButton: "DEVAM",
- outOfStock: "Stokta yok",
- },
- rechargerDisplay: {
- title: "ŞARJ EDİLİYOR...",
- remainingTimeText: "KALAN SÜRE",
- remainingTimeValue: "{0} dk {1} sn",
- },
- fuelConsumptionChart: {
- title: "Yakıt tüketim grafiği",
- chartLabels: {
- fuel: "Yakıt (%)",
- speed: "Hız (km/s)",
- consumption: "Tüketim (L/s)",
- shortSeconds: "{0}s",
- },
- footer: {
- focus: "Odağı değiştirmek için F3",
- toggleRecording: "Kaydı Aç/Kapat",
- recordsLength: "Geçmiş Uzunluğu ({0}s)",
- },
- },
-};
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["tr"] = {
+ pumpInterface: {
+ stationStock: "{0} L",
+ vehicleFuel: "{0} L",
+ confirm: "ONAYLA",
+ vehicleFuelTooltip: "Mevcut Yakıt / Depo Kapasitesi",
+ fuelTypes: {
+ regular: "Normal",
+ plus: "Plus",
+ premium: "Premium",
+ diesel: "Dizel",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "L",
+ carTank: "Araç Deposu",
+ remaining: "Kalan",
+ },
+ confirmRefuelModal: {
+ title: "Yakıt Alımını Onayla",
+ description: "{0}L {1} yakıtı {2} karşılığında satın alıyorsunuz.",
+ paymentBank: "Banka ile öde",
+ paymentCash: "Nakit ile öde",
+ },
+ confirmBuyJerryCanModal: {
+ title: "Satın Alımı Onayla",
+ paymentBank: "Banka ile öde",
+ paymentCash: "Nakit ile öde",
+ },
+ confirmFuelChangeModal: {
+ title: "Yakıtlar Karıştırılamaz",
+ description: "⚠️ Araçtaki yakıt türünü değiştirmek için depo boşaltılacaktır.",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "ŞARJ CİHAZI TÜRÜ",
+ fast: {
+ title: "HIZLI",
+ power: "220kW",
+ },
+ normal: {
+ title: "NORMAL",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "MİKTAR SEÇİN",
+ typeSelected: "{0} ŞARJ CİHAZI",
+ placeholder: "Miktar",
+ timeToRechargeText: "Şarj süresi:",
+ timeToRechargeValue: "{0} dk {1} sn",
+ },
+ chargerPayment: {
+ title: "ÖDEME YÖNTEMİ",
+ money: "NAKİT",
+ bank: "BANKA",
+ payButton: "{0} ÖDE",
+ },
+ continueButton: "DEVAM",
+ outOfStock: "Stokta yok",
+ },
+ rechargerDisplay: {
+ title: "ŞARJ EDİLİYOR...",
+ remainingTimeText: "KALAN SÜRE",
+ remainingTimeValue: "{0} dk {1} sn",
+ },
+ fuelConsumptionChart: {
+ title: "Yakıt tüketim grafiği",
+ chartLabels: {
+ fuel: "Yakıt (%)",
+ speed: "Hız (km/s)",
+ consumption: "Tüketim (L/s)",
+ shortSeconds: "{0}s",
+ },
+ footer: {
+ focus: "Odağı değiştirmek için F3",
+ toggleRecording: "Kaydı Aç/Kapat",
+ recordsLength: "Geçmiş Uzunluğu ({0}s)",
+ },
+ },
+};
diff --git a/resources/[carscripts]/lc_fuel/nui/lang/zh-cn.js b/resources/[carscripts]/lc_fuel/nui/lang/zh-cn.js
index d925cafc9..997c09416 100644
--- a/resources/[carscripts]/lc_fuel/nui/lang/zh-cn.js
+++ b/resources/[carscripts]/lc_fuel/nui/lang/zh-cn.js
@@ -1,85 +1,85 @@
-if (Lang == undefined) {
- var Lang = [];
-}
-Lang["zh-cn"] = {
- pumpInterface: {
- stationStock: "{0} 升(L)",
- vehicleFuel: "{0} 升(L)",
- confirm: "确认",
- vehicleFuelTooltip: "当前燃料 / 油箱容量",
- fuelTypes: {
- regular: "92号燃油",
- plus: "95号燃油",
- premium: "98号燃油",
- diesel: "柴油",
- },
- },
- pumpRefuelDisplay: {
- liters: "升(L)",
- carTank: "车辆油箱",
- remaining: "剩余容量",
- },
- confirmRefuelModal: {
- title: "加油确认",
- description: "您正在为车牌号 {2} 的车辆补充 {0} 升 {1} 类燃油",
- paymentBank: "银行结算",
- paymentCash: "现金结算",
- },
- confirmBuyJerryCanModal: {
- title: "确认购买",
- paymentBank: "银行结算",
- paymentCash: "现金结算",
- },
- confirmFuelChangeModal: {
- title: "燃油类型变更提示",
- description: "⚠️ 更换燃油种类前请确保油箱完全排空",
- },
- electricInterface: {
- chargerType: {
- title: "充电规格选择",
- fast: {
- title: "极速充电",
- power: "220kW",
- },
- normal: {
- title: "标准充电",
- power: "100kW",
- },
- pricePerKWh: "{0}/kWh",
- },
- chargerAmount: {
- title: "充电金额设定",
- typeSelected: "充电桩 {0} 台",
- placeholder: "输入金额",
- timeToRechargeText: "预计充电时长:",
- timeToRechargeValue: "{0} 分 {1} 秒",
- },
- chargerPayment: {
- title: "支付方式选择",
- money: "现金结算",
- bank: "银行解锁",
- payButton: "支付 {0}",
- },
- continueButton: "下一步",
- outOfStock: "库存不足",
- },
- rechargerDisplay: {
- title: "充电中...",
- remainingTimeText: "剩余充电时间",
- remainingTimeValue: "{0} 分 {1} 秒",
- },
- fuelConsumptionChart: {
- title: "燃料消耗图表",
- chartLabels: {
- fuel: "燃料 (%)",
- speed: "速度 (km/h)",
- consumption: "消耗 (L/s)",
- shortSeconds: "{0}秒",
- },
- footer: {
- focus: "按F3切换焦点",
- toggleRecording: "切换录制",
- recordsLength: "历史长度({0}秒)",
- },
- },
+if (Lang == undefined) {
+ var Lang = [];
+}
+Lang["zh-cn"] = {
+ pumpInterface: {
+ stationStock: "{0} 升(L)",
+ vehicleFuel: "{0} 升(L)",
+ confirm: "确认",
+ vehicleFuelTooltip: "当前燃料 / 油箱容量",
+ fuelTypes: {
+ regular: "92号燃油",
+ plus: "95号燃油",
+ premium: "98号燃油",
+ diesel: "柴油",
+ },
+ },
+ pumpRefuelDisplay: {
+ liters: "升(L)",
+ carTank: "车辆油箱",
+ remaining: "剩余容量",
+ },
+ confirmRefuelModal: {
+ title: "加油确认",
+ description: "您正在为车牌号 {2} 的车辆补充 {0} 升 {1} 类燃油",
+ paymentBank: "银行结算",
+ paymentCash: "现金结算",
+ },
+ confirmBuyJerryCanModal: {
+ title: "确认购买",
+ paymentBank: "银行结算",
+ paymentCash: "现金结算",
+ },
+ confirmFuelChangeModal: {
+ title: "燃油类型变更提示",
+ description: "⚠️ 更换燃油种类前请确保油箱完全排空",
+ },
+ electricInterface: {
+ chargerType: {
+ title: "充电规格选择",
+ fast: {
+ title: "极速充电",
+ power: "220kW",
+ },
+ normal: {
+ title: "标准充电",
+ power: "100kW",
+ },
+ pricePerKWh: "{0}/kWh",
+ },
+ chargerAmount: {
+ title: "充电金额设定",
+ typeSelected: "充电桩 {0} 台",
+ placeholder: "输入金额",
+ timeToRechargeText: "预计充电时长:",
+ timeToRechargeValue: "{0} 分 {1} 秒",
+ },
+ chargerPayment: {
+ title: "支付方式选择",
+ money: "现金结算",
+ bank: "银行解锁",
+ payButton: "支付 {0}",
+ },
+ continueButton: "下一步",
+ outOfStock: "库存不足",
+ },
+ rechargerDisplay: {
+ title: "充电中...",
+ remainingTimeText: "剩余充电时间",
+ remainingTimeValue: "{0} 分 {1} 秒",
+ },
+ fuelConsumptionChart: {
+ title: "燃料消耗图表",
+ chartLabels: {
+ fuel: "燃料 (%)",
+ speed: "速度 (km/h)",
+ consumption: "消耗 (L/s)",
+ shortSeconds: "{0}秒",
+ },
+ footer: {
+ focus: "按F3切换焦点",
+ toggleRecording: "切换录制",
+ recordsLength: "历史长度({0}秒)",
+ },
+ },
};
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/panel.js b/resources/[carscripts]/lc_fuel/nui/panel.js
index 78477f9e9..1620cde56 100644
--- a/resources/[carscripts]/lc_fuel/nui/panel.js
+++ b/resources/[carscripts]/lc_fuel/nui/panel.js
@@ -1,724 +1,724 @@
-let currentPumpData;
-let selectedFuelType;
-let fuelTypeWarnSent;
-
-// Fuel Consumption Chart Dialog
-let fuelChart, speedChart, consumptionChart;
-let toggleChartFocusShortcut;
-let chartTimestampsIndex = 1;
-let chartTimestamps = [ 15, 30, 60, 90, 120, 150, 180 ];
-let isRecording;
-
-window.addEventListener("message", async function(event) {
- const item = event.data;
- if (item.data) {
- currentPumpData = item.data;
- }
- if (item.resourceName) {
- Utils.setResourceName(item.resourceName);
- }
- if (item.utils) {
- await Utils.loadLanguageModules(item.utils);
- Utils.post("setNuiVariablesLoaded", null, "setNuiVariablesLoaded");
- }
- if (item.type === "copyToClipboard") {
- const el = document.createElement("textarea");
- el.value = item.text;
- document.body.appendChild(el);
- el.select();
- document.execCommand("copy");
- document.body.removeChild(el);
- }
- if (item.openMainUI) {
- if (currentPumpData.isElectric) {
- $("#electric-time-to-recharge").html(`${Utils.translate("electricInterface.chargerAmount.timeToRechargeText")} `);
-
- $("#electric-charger-type-title").text(Utils.translate("electricInterface.chargerType.title"));
- $("#electric-charger-type-fast").text(Utils.translate("electricInterface.chargerType.fast.title"));
- $("#electric-charger-type-normal").text(Utils.translate("electricInterface.chargerType.normal.title"));
- $("#electric-charger-type-label-item-fast-price").text(Utils.translate("electricInterface.chargerType.pricePerKWh").format(Utils.currencyFormat(currentPumpData.pricePerLiter.electricfast)));
- $("#electric-charger-type-label-item-normal-price").text(Utils.translate("electricInterface.chargerType.pricePerKWh").format(Utils.currencyFormat(currentPumpData.pricePerLiter.electricnormal)));
- $("#electric-charger-type-label-item-fast-power").text(Utils.translate("electricInterface.chargerType.fast.power"));
- $("#electric-charger-type-label-item-normal-power").text(Utils.translate("electricInterface.chargerType.normal.power"));
- $("#electric-charger-continue-type-button").text(Utils.translate("electricInterface.continueButton"));
-
- $("#electric-charger-amount-title").text(Utils.translate("electricInterface.chargerAmount.title"));
- $("#electric-charger-amount-input").attr("placeholder", Utils.translate("electricInterface.chargerAmount.placeholder"));
- $("#electric-charger-continue-amount-button").text(Utils.translate("electricInterface.continueButton"));
-
- $("#electric-charger-payment-title").text(Utils.translate("electricInterface.chargerPayment.title"));
- $("#electric-charger-payment-bank").text(Utils.translate("electricInterface.chargerPayment.bank"));
- $("#electric-charger-payment-money").text(Utils.translate("electricInterface.chargerPayment.money"));
-
- if (currentPumpData.stationStock.electricfast == 0) {
- $("#electric-charger-fast-label-wrapper")
- .attr("data-tooltip", Utils.translate("electricInterface.outOfStock"))
- .attr("data-tooltip-location", "top");
- $("#charger-type-fast").prop("disabled", true);
- } else {
- $("#electric-charger-fast-label-wrapper")
- .removeAttr("data-tooltip")
- .removeAttr("data-tooltip-location");
- $("#charger-type-fast").prop("disabled", false);
- }
-
- if (currentPumpData.stationStock.electricnormal == 0) {
- $("#electric-charger-normal-label-wrapper")
- .attr("data-tooltip", Utils.translate("electricInterface.outOfStock"))
- .attr("data-tooltip-location", "top");
- $("#charger-type-normal").prop("disabled", true);
- } else {
- $("#electric-charger-normal-label-wrapper")
- .removeAttr("data-tooltip")
- .removeAttr("data-tooltip-location");
- $("#charger-type-normal").prop("disabled", false);
- }
-
- $(".electric-charger-type-container").css("display", "");
- $(".electric-charger-amount-container").css("display", "none");
- $(".electric-charger-payment-container").css("display", "none");
- $("#electric-charger-container").fadeIn(200);
- } else {
- if (currentPumpData.pumpModel == "prop_gas_pump_1a" || currentPumpData.pumpModel == "prop_gas_pump_1b" || currentPumpData.pumpModel == "prop_gas_pump_1c" || currentPumpData.pumpModel == "prop_gas_pump_1d") {
- $("#gas-pump-container-image").attr("src", `images/${currentPumpData.pumpModel}.png`);
- } else {
- $("#gas-pump-container-image").attr("src", `images/prop_gas_pump_1b.png`);
- }
- fuelTypeWarnSent = false;
- changeSelectedFuelType(currentPumpData.currentFuelType);
- $(".vehicle-fuel").text(Utils.translate("pumpInterface.vehicleFuel").format(`${Utils.numberFormat(currentPumpData.vehicleFuel, 1)} / ${Utils.numberFormat(currentPumpData.vehicleTankSize, 0)}`));
- $(".vehicle-fuel").attr("data-tooltip", Utils.translate("pumpInterface.vehicleFuelTooltip"));
- $(".bank-balance").text(Utils.currencyFormat(currentPumpData.bankBalance, 2));
- $(".cash-balance").text(Utils.currencyFormat(currentPumpData.cashBalance, 2));
-
- $(".fuel-type-button.regular").text(Utils.translate("pumpInterface.fuelTypes.regular"));
- $(".fuel-type-button.plus").text(Utils.translate("pumpInterface.fuelTypes.plus"));
- $(".fuel-type-button.premium").text(Utils.translate("pumpInterface.fuelTypes.premium"));
- $(".fuel-type-button.diesel").text(Utils.translate("pumpInterface.fuelTypes.diesel"));
- $(".confirm-button").text(Utils.translate("pumpInterface.confirm"));
-
- $("#confirm-refuel-payment-modal-title").text(Utils.translate("confirmRefuelModal.title"));
- $("#confirm-refuel-payment-modal-pay-bank").text(Utils.translate("confirmRefuelModal.paymentBank"));
- $("#confirm-refuel-payment-modal-pay-cash").text(Utils.translate("confirmRefuelModal.paymentCash"));
-
- $("#confirm-jerry-can-payment-modal-title").text(Utils.translate("confirmBuyJerryCanModal.title"));
- $("#confirm-jerry-can-payment-modal-desc").text(Utils.currencyFormat(currentPumpData.jerryCan.price, 2));
- $("#confirm-jerry-can-payment-modal-pay-bank").text(Utils.translate("confirmBuyJerryCanModal.paymentBank"));
- $("#confirm-jerry-can-payment-modal-pay-cash").text(Utils.translate("confirmBuyJerryCanModal.paymentCash"));
-
- $("#confirm-fuel-type-modal-title").text(Utils.translate("confirmFuelChangeModal.title"));
- $("#confirm-fuel-type-modal-desc").text(Utils.translate("confirmFuelChangeModal.description"));
- $("#confirm-fuel-type-modal-confirm").text(Utils.translate("confirmation_modal_confirm_button"));
- $("#confirm-fuel-type-modal-cancel").text(Utils.translate("confirmation_modal_cancel_button"));
-
- if (!currentPumpData.jerryCan.enabled) {
- $(".gas-pump-interactive-button").css("display", "none");
- }
-
- updateFuelAmountDisplay(true);
-
- $("#gas-pump-container").fadeIn(200);
- }
- }
- if (item.hideMainUI) {
- $("#gas-pump-container").fadeOut(200);
- $("#electric-charger-container").fadeOut(200);
- }
- if (item.showRefuelDisplay) {
- if (item.isElectric) {
- let percentageOfTankFilled = (item.currentDisplayFuelAmount / item.currentVehicleTankSize) * 100;
- $("#recharge-display-title").text(Utils.translate("rechargerDisplay.title"));
- $("#recharge-display-battery-level-span").text(`${Utils.numberFormat(percentageOfTankFilled, 0)}%`);
- $("#recharge-display-battery-liquid").css("width", `${percentageOfTankFilled}%`);
- $("#recharge-display-remaining-time-title").text(Utils.translate("rechargerDisplay.remainingTimeText"));
- updateRechargeDisplay((item.currentVehicleTankSize - item.currentDisplayFuelAmount), item.fuelTypePurchased);
- $("#recharge-display").fadeIn(200);
- } else {
- $("#refuel-display-pump-value").text(Utils.numberFormat(item.remainingFuelAmount, 2));
- $("#refuel-display-car-value").text(`${Utils.numberFormat(item.currentDisplayFuelAmount, 2)}/${Utils.numberFormat(item.currentVehicleTankSize, 2)}`);
- $(".refuel-display-liters").text(Utils.translate("pumpRefuelDisplay.liters"));
- $("#refuel-display-car-label").text(Utils.translate("pumpRefuelDisplay.carTank"));
- $("#refuel-display-pump-label").text(Utils.translate("pumpRefuelDisplay.remaining"));
- $("#refuel-display").fadeIn(200);
- }
- }
- if (item.hideRefuelDisplay) {
- $("#refuel-display").fadeOut(200);
- $("#recharge-display").fadeOut(200);
- }
- if (item.showFuelConsumptionChart) {
- toggleChartFocusShortcut = item.focusShortcut;
- isRecording = item.isRecording;
-
- createFuelConsumptionChartObject();
- openFuelConsumptionChart();
- setFuelConsumptionChartPosition(item.position);
- updateFuelConsumptionChart({ fuel: null, speed: null, consumption: null });
- }
- if (item.updateFuelConsumptionChart) {
- updateFuelConsumptionChart(item.fuelConsumptionData);
- }
- if (item.hideFuelConsumptionChart) {
- updateFuelConsumptionChart({ fuel: null, speed: null, consumption: null });
- $("#chart-dialog").fadeOut();
- // fuelChart.destroy();
- // speedChart.destroy();
- // consumptionChart.destroy();
- }
-});
-
-function updateRechargeDisplay(remainingFuelAmount, chargerType) {
- if (chargerType == "electricfast") chargerType = "fast";
- if (chargerType == "electricnormal") chargerType = "normal";
- if (chargerType && (chargerType === "fast" || chargerType === "normal")) {
- // Calculate the time to recharge based on remaining fuel amount and charger type's time per unit
- let timeToRecharge = remainingFuelAmount * currentPumpData.electric.chargeTypes[chargerType].time;
-
- // Convert time to minutes and seconds
- let timeToRechargeMinutes = Math.floor(timeToRecharge / 60);
- let timeToRechargeSeconds = timeToRecharge % 60;
-
- // Update the display with calculated time
- $("#recharge-display-remaining-time-value").text(Utils.translate("rechargerDisplay.remainingTimeValue").format(Utils.numberFormat(timeToRechargeMinutes, 0), Utils.numberFormat(timeToRechargeSeconds, 0)));
- } else {
- console.log("Invalid charger type or no charger type selected");
- }
-}
-
-/*=================
- FUNCTIONS
-=================*/
-
-function changeSelectedFuelType(fuelType) {
- if (fuelType == "regular" || fuelType == "plus" || fuelType == "premium" || fuelType == "diesel") {
- $(".fuel-type-button").removeClass("selected");
- $(`.fuel-type-button.${fuelType}`).addClass("selected");
-
- $(".price-per-liter").text(Utils.currencyFormat(currentPumpData.pricePerLiter[fuelType], 2));
- $(".station-stock").text(Utils.translate("pumpInterface.stationStock").format(Utils.numberFormat(currentPumpData.stationStock[fuelType])));
- selectedFuelType = fuelType;
- } else {
- console.log("Invalid fuel type chosen: " + fuelType);
- }
-}
-
-// Show the modal when confirmRefuel is called
-function confirmRefuel() {
- if (fuelTypeWarnSent == false && currentPumpData.currentFuelType != selectedFuelType && currentPumpData.vehicleFuel > 0) {
- fuelTypeWarnSent = true;
- $("#confirm-fuel-type-modal").fadeIn();
- } else {
- let $input = $("#input-fuel-amount");
- let fuelAmount = parseInt($input.val());
- $("#confirm-refuel-payment-modal-desc").text(Utils.translate("confirmRefuelModal.description").format(fuelAmount, Utils.translate("pumpInterface.fuelTypes."+selectedFuelType), Utils.currencyFormat(fuelAmount * currentPumpData.pricePerLiter[selectedFuelType])));
- $("#confirm-refuel-payment-modal").fadeIn();
- }
-}
-
-// Empty vehicle's tank after user confirm fuel type change
-function changeVehicleFuelType() {
- closeModal();
- Utils.post("changeVehicleFuelType", { selectedFuelType });
- currentPumpData.vehicleFuel = 0;
- $(".vehicle-fuel").text(Utils.translate("pumpInterface.vehicleFuel").format(Utils.numberFormat(currentPumpData.vehicleFuel, 2)));
-}
-
-// Confirm the buy jerry can action
-function openBuyJerryCanModal() {
- closeModal();
- $("#confirm-jerry-can-payment-modal").fadeIn();
-}
-
-// Hide the modal
-function closeModal() {
- $(".modal").fadeOut();
-}
-
-function confirmRefuelPayment(paymentMethod) {
- let $input = $("#input-fuel-amount");
- let fuelAmount = parseInt($input.val());
- Utils.post("confirmRefuel", { selectedFuelType, fuelAmount, paymentMethod });
- closeModal();
-}
-
-function confirmJerryCanPayment(paymentMethod) {
- Utils.post("confirmJerryCanPurchase", { paymentMethod });
- closeModal();
-}
-
-function increaseZoom() {
- // Get the current zoom level
- let currentZoom = parseFloat($("#gas-pump-container").css("zoom")) || 1;
-
- // Increase zoom by 5%
- let newZoom = currentZoom + 0.05;
-
- // Limit the zoom to a maximum of 1.4 (140%)
- if (newZoom > 1.4) {
- newZoom = 1.4;
- }
-
- // Apply the new zoom level
- $("#gas-pump-container").css("zoom", newZoom);
-}
-
-function decreaseZoom() {
- // Get the current zoom level
- let currentZoom = parseFloat($("#gas-pump-container").css("zoom")) || 1;
-
- // Decrease zoom by 5%
- let newZoom = currentZoom - 0.05;
-
- // Limit the zoom to a minimum of 0.8 (80%)
- if (newZoom < 0.8) {
- newZoom = 0.8;
- }
-
- // Apply the new zoom level
- $("#gas-pump-container").css("zoom", newZoom);
-}
-
-// Function to update the display with the 'L' suffix
-function updateFuelAmountDisplay(setToMax = false) {
- let $input = $("#input-fuel-amount");
- let value = parseInt($input.val());
-
- // Set value to 1 if it's not a positive number
- if (isNaN(value) || value <= 0) {
- value = 1;
- }
-
- // Don't let it purchase more L than the vehicle can hold in the tank
- if (setToMax || (!isNaN(value) && value > currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
- value = Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel);
- }
-
- $input.val(value + " L");
-}
-
-// Pagination for electric chargers
-function chargerTypeContinue() {
- let chargerType = getSelectedChargerType();
- if (chargerType && (chargerType == "fast" || chargerType == "normal")) {
- $("#electric-charger-amount-input").val(Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel));
- calculateTimeToRecharge();
- $("#electric-charger-amount-type-selected").text(Utils.translate("electricInterface.chargerAmount.typeSelected").format(Utils.translate(`electricInterface.chargerType.${chargerType}.title`)));
- $(".electric-charger-type-container").css("display", "none");
- $(".electric-charger-amount-container").css("display", "");
- }
-}
-
-function chargerAmountContinue() {
- let $input = $("#electric-charger-amount-input");
- let currentValue = parseInt($input.val()) || 0;
- let newWidthPercentage = ((currentPumpData.vehicleFuel / currentPumpData.vehicleTankSize) * 100) + ((currentValue / currentPumpData.vehicleTankSize) * 100);
-
- if (currentValue <= 0 || newWidthPercentage > 100) {
- return;
- }
-
- let chargerType = getSelectedChargerType();
- $("#electric-charger-pay-button").text(Utils.translate("electricInterface.chargerPayment.payButton").format(Utils.currencyFormat(currentValue * currentPumpData.pricePerLiter["electric"+chargerType], 2)));
- $(".electric-charger-amount-container").css("display", "none");
- $(".electric-charger-payment-container").css("display", "");
-}
-
-function chargerAmountReturn() {
- $(".electric-charger-type-container").css("display", "");
- $(".electric-charger-amount-container").css("display", "none");
- $(".electric-charger-payment-container").css("display", "none");
-}
-
-function confirmRecharge() {
- let $input = $("#electric-charger-amount-input");
- let fuelAmount = parseInt($input.val()) || 0;
- Utils.post("confirmRefuel", { selectedFuelType: "electric" + getSelectedChargerType(), fuelAmount, paymentMethod: getSelectedElectricPaymentMethod() });
-}
-
-function chargerPaymentReturn() {
- $(".electric-charger-type-container").css("display", "none");
- $(".electric-charger-amount-container").css("display", "");
- $(".electric-charger-payment-container").css("display", "none");
-}
-
-function getSelectedChargerType() {
- const selectedInput = $("input[name='charger-type']:checked");
- return selectedInput.length && !selectedInput.prop("disabled") ? selectedInput.val() : null;
-}
-
-function getSelectedElectricPaymentMethod() {
- const selectedInput = $("input[name='charger-payment']:checked");
- return selectedInput.length ? selectedInput.val() : null;
-}
-
-function calculateTimeToRecharge() {
- let $input = $("#electric-charger-amount-input");
- let currentValue = parseInt($input.val());
-
- // Allow empty input temporarily; validate only non-empty values
- if ($input.val().trim() === "" || isNaN(currentValue) || currentValue <= 0) {
- currentValue = 0;
- }
-
- if (currentValue > 1000) {
- currentValue = 1000;
- $input.val(currentValue);
- }
-
- let chargerType = getSelectedChargerType();
- if (chargerType && (chargerType == "fast" || chargerType == "normal")) {
- let timeToRecharge = currentValue * currentPumpData.electric.chargeTypes[chargerType].time;
-
- // Calculate minutes and seconds
- let timeToRechargeMinutes = Math.floor(timeToRecharge / 60);
- let timeToRechargeSeconds = timeToRecharge % 60;
-
- $("#electric-time-to-recharge-value").text(Utils.translate("electricInterface.chargerAmount.timeToRechargeValue").format(Utils.numberFormat(timeToRechargeMinutes, 0), Utils.numberFormat(timeToRechargeSeconds, 0)));
-
- let newWidthPercentage = ((currentPumpData.vehicleFuel / currentPumpData.vehicleTankSize) * 100) + ((currentValue / currentPumpData.vehicleTankSize) * 100);
- $("#electric-amount-progress-bar").css("width", newWidthPercentage + "%");
-
- if (newWidthPercentage > 100) {
- $("#electric-amount-progress-bar").css("background", "red");
- } else {
- $("#electric-amount-progress-bar").css("background", "");
- }
- } else {
- console.log("No charger type selected");
- }
-}
-
-/*===================
- CHART DIALOG
-===================*/
-
-function openFuelConsumptionChart() {
- const $dialog = $("#chart-dialog");
-
- $("#chart-dialog-title").text(Utils.translate("fuelConsumptionChart.title"));
- $("#chart-dialog-footer-text").text(Utils.translate("fuelConsumptionChart.footer.focus"));
- $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
- $("#start-stop-recording-label").text(Utils.translate("fuelConsumptionChart.footer.toggleRecording"));
- $("#start-stop-recording").prop("checked", isRecording);
-
- $dialog.css({
- right: "",
- bottom: "",
- display: "flex",
- }).fadeIn();
-
- $dialog.draggable({
- handle: ".dialog-header",
- }).resizable({
- minHeight: 450,
- minWidth: 300,
- maxHeight: $(window).height()*0.8,
- maxWidth: $(window).width()*0.8,
- });
- speedChart.resize();
- consumptionChart.resize();
- fuelChart.resize();
-}
-
-function setFuelConsumptionChartPosition(position) {
- const $dialog = $("#chart-dialog");
- const windowWidth = $(window).width();
- const dialogWidth = $dialog.outerWidth();
-
- let top = 10;
- let left;
-
- // Horizontal position
- if (position === "left") {
- left = 10;
- } else {
- left = windowWidth - dialogWidth - 10;
- }
-
- $dialog.css({
- top: `${top}px`,
- left: `${left}px`,
- });
-}
-
-
-function updateFuelConsumptionChart(latestData) {
- const now = Date.now();
-
- if (fuelChart && speedChart && consumptionChart) {
- fuelChart.data.datasets[0].data.push({ x: now, y: latestData.fuel });
- speedChart.data.datasets[0].data.push({ x: now, y: latestData.speed });
- consumptionChart.data.datasets[0].data.push({ x: now, y: latestData.consumption });
- }
- fuelChart.update("quiet");
- speedChart.update("quiet");
- consumptionChart.update("quiet");
-}
-
-function createFuelConsumptionChartObject() {
- if (fuelChart || speedChart || consumptionChart) { return; }
-
- Chart.defaults.color = "rgba(218, 218, 218, 0.73)";
- Chart.overrides.line.spanGaps = false;
-
- const baseOptions = {
- responsive: true,
- maintainAspectRatio: false,
- elements: { point: { radius: 0 } },
- animation: false,
- interaction: { mode: "index", intersect: false },
- plugins: {
- legend: {
- position: "bottom",
- labels: { boxWidth: 3, boxHeight: 3 },
- },
- streaming: {
- frameRate: 10,
- },
- },
- scales: {
- x: {
- type: "realtime",
- realtime: {
- duration: 30000,
- refresh: 1000,
- delay: 1000,
- },
- },
- y: {
- beginAtZero: true,
- },
- },
- };
-
- // Fuel Chart
-
- fuelChart = new Chart(document.getElementById("fuel-chart"), {
- type: "line",
- data: {
- datasets: [{
- label: Utils.translate("fuelConsumptionChart.chartLabels.fuel"),
- data: [],
- borderColor: "#FFD800",
- cubicInterpolationMode: "monotone",
- }],
- },
- options: {
- ...baseOptions,
- scales: {
- ...baseOptions.scales,
- y: {
- ...baseOptions.scales.y,
- suggestedMax: 100,
- title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.fuel") },
- },
- },
- },
- });
-
- // Speed Chart
-
- speedChart = new Chart(document.getElementById("speed-chart"), {
- type: "line",
- data: {
- datasets: [{
- label: Utils.translate("fuelConsumptionChart.chartLabels.speed"),
- data: [],
- borderColor: "#0026FF",
- cubicInterpolationMode: "monotone",
- }],
- },
- options: {
- ...baseOptions,
- scales: {
- ...baseOptions.scales,
- y: {
- ...baseOptions.scales.y,
- suggestedMax: 140,
- title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.speed") },
- },
- },
- },
- });
-
- // Consumption Chart
-
- consumptionChart = new Chart(document.getElementById("consumption-chart"), {
- type: "line",
- data: {
- datasets: [{
- label: Utils.translate("fuelConsumptionChart.chartLabels.consumption"),
- data: [],
- borderColor: "#7F0000",
- cubicInterpolationMode: "monotone",
- }],
- },
- options: {
- ...baseOptions,
- scales: {
- ...baseOptions.scales,
- y: {
- ...baseOptions.scales.y,
- suggestedMax: 0.3,
- title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.consumption") },
- },
- },
- },
- });
-}
-
-
-/*=================
- LISTENERS
-=================*/
-
-$(window).click(function(event) {
- // Close the modal when clicking outside of it
- if ($(event.target).is(".modal")) {
- closeModal();
- }
-});
-
-$(document).on("keydown", function(event) {
- // Handle press of Esc key
- if (event.key === "Escape" || event.keyCode === 27) {
- // Check if the modal is open by checking if it's visible
- if ($("#chart-dialog").is(":visible")) {
- closeFuelConsumptionChartUI();
- } else if ($(".modal").is(":visible")) {
- closeModal();
- } else {
- closeUI();
- }
- }
- if (event.key === toggleChartFocusShortcut
- || event.key === "w" || event.key === "W"
- || event.key === "a" || event.key === "A"
- || event.key === "d" || event.key === "D"
- || event.key === "s" || event.key === "S") {
- // Check if the modal is open by checking if it's visible
- if ($("#chart-dialog").is(":visible")) {
- removeFocusFuelConsumptionChartUI();
- }
- }
-});
-
-$(document).ready(function() {
- // Handle the add button
- $(".refuel-add").click(function() {
- let $input = $("#input-fuel-amount");
- let currentValue = parseInt($input.val()) || 0;
- if (currentValue < Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
- $input.val((currentValue + 1) + " L");
- }
- });
- $(".recharge-add").click(function() {
- let $input = $("#electric-charger-amount-input");
- let currentValue = parseInt($input.val()) || 0;
- if (currentValue < Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
- $input.val((currentValue + 1));
- calculateTimeToRecharge();
- }
- });
-
- // Handle the sub button
- $(".refuel-sub").click(function() {
- let $input = $("#input-fuel-amount");
- let currentValue = parseInt($input.val()) || 0;
- if (currentValue > 1) {
- $input.val((currentValue - 1) + " L");
- }
- });
- $(".recharge-sub").click(function() {
- let $input = $("#electric-charger-amount-input");
- let currentValue = parseInt($input.val()) || 0;
- if (currentValue > 1) {
- $input.val((currentValue - 1));
- calculateTimeToRecharge();
- }
- });
-
- // Remove 'L' suffix on focus to allow numeric input, and add it back on blur
- $("#input-fuel-amount").on("focus", function() {
- $(this).val(parseInt($(this).val()) || 1);
- }).on("blur", function() {
- updateFuelAmountDisplay();
- });
-
- // Recalculate time when change input
- $("#electric-charger-amount-input").on("input", function() {
- calculateTimeToRecharge();
- });
- $("#electric-charger-amount-input").on("blur", function() {
- let $input = $(this);
- let currentValue = parseInt($input.val());
-
- // If invalid, reset to 0
- if (isNaN(currentValue) || currentValue <= 0) {
- $input.val(0);
- }
- });
-
- // Handle chart buttons
- $("#start-stop-recording").change(function() {
- if ($(this).is(":checked")) {
- startRecordingGraph();
- } else {
- stopRecordingGraph();
- }
- });
-
- $("#increase-chart-recording").click(function() {
- if (chartTimestampsIndex < chartTimestamps.length - 1) {
- chartTimestampsIndex++;
- $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
- changeRecordingIndexGraph();
- }
- });
-
- $("#decrease-chart-recording").click(function() {
- if (chartTimestampsIndex > 0) {
- chartTimestampsIndex--;
- $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
- changeRecordingIndexGraph();
- }
- });
-});
-
-
-/*=================
- CALLBACKS
-=================*/
-
-function closeUI(){
- Utils.post("close","");
-}
-
-function stopRecordingGraph(){
- fuelChart.options.scales.x.realtime.pause = true;
- speedChart.options.scales.x.realtime.pause = true;
- consumptionChart.options.scales.x.realtime.pause = true;
- Utils.post("stopRecordingGraph","");
-}
-
-function startRecordingGraph(){
- fuelChart.options.scales.x.realtime.pause = false;
- speedChart.options.scales.x.realtime.pause = false;
- consumptionChart.options.scales.x.realtime.pause = false;
- Utils.post("startRecordingGraph","");
-}
-
-function changeRecordingIndexGraph(){
- fuelChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
- speedChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
- consumptionChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
- Utils.post("changeRecordingIndexGraph",chartTimestampsIndex);
-}
-
-function closeFuelConsumptionChartUI(){
- Utils.post("closeFuelConsumptionChartUI","");
-}
-
-function removeFocusFuelConsumptionChartUI(){
- Utils.post("removeFocusFuelConsumptionChartUI","");
+let currentPumpData;
+let selectedFuelType;
+let fuelTypeWarnSent;
+
+// Fuel Consumption Chart Dialog
+let fuelChart, speedChart, consumptionChart;
+let toggleChartFocusShortcut;
+let chartTimestampsIndex = 1;
+let chartTimestamps = [ 15, 30, 60, 90, 120, 150, 180 ];
+let isRecording;
+
+window.addEventListener("message", async function(event) {
+ const item = event.data;
+ if (item.data) {
+ currentPumpData = item.data;
+ }
+ if (item.resourceName) {
+ Utils.setResourceName(item.resourceName);
+ }
+ if (item.utils) {
+ await Utils.loadLanguageModules(item.utils);
+ Utils.post("setNuiVariablesLoaded", null, "setNuiVariablesLoaded");
+ }
+ if (item.type === "copyToClipboard") {
+ const el = document.createElement("textarea");
+ el.value = item.text;
+ document.body.appendChild(el);
+ el.select();
+ document.execCommand("copy");
+ document.body.removeChild(el);
+ }
+ if (item.openMainUI) {
+ if (currentPumpData.isElectric) {
+ $("#electric-time-to-recharge").html(`${Utils.translate("electricInterface.chargerAmount.timeToRechargeText")} `);
+
+ $("#electric-charger-type-title").text(Utils.translate("electricInterface.chargerType.title"));
+ $("#electric-charger-type-fast").text(Utils.translate("electricInterface.chargerType.fast.title"));
+ $("#electric-charger-type-normal").text(Utils.translate("electricInterface.chargerType.normal.title"));
+ $("#electric-charger-type-label-item-fast-price").text(Utils.translate("electricInterface.chargerType.pricePerKWh").format(Utils.currencyFormat(currentPumpData.pricePerLiter.electricfast)));
+ $("#electric-charger-type-label-item-normal-price").text(Utils.translate("electricInterface.chargerType.pricePerKWh").format(Utils.currencyFormat(currentPumpData.pricePerLiter.electricnormal)));
+ $("#electric-charger-type-label-item-fast-power").text(Utils.translate("electricInterface.chargerType.fast.power"));
+ $("#electric-charger-type-label-item-normal-power").text(Utils.translate("electricInterface.chargerType.normal.power"));
+ $("#electric-charger-continue-type-button").text(Utils.translate("electricInterface.continueButton"));
+
+ $("#electric-charger-amount-title").text(Utils.translate("electricInterface.chargerAmount.title"));
+ $("#electric-charger-amount-input").attr("placeholder", Utils.translate("electricInterface.chargerAmount.placeholder"));
+ $("#electric-charger-continue-amount-button").text(Utils.translate("electricInterface.continueButton"));
+
+ $("#electric-charger-payment-title").text(Utils.translate("electricInterface.chargerPayment.title"));
+ $("#electric-charger-payment-bank").text(Utils.translate("electricInterface.chargerPayment.bank"));
+ $("#electric-charger-payment-money").text(Utils.translate("electricInterface.chargerPayment.money"));
+
+ if (currentPumpData.stationStock.electricfast == 0) {
+ $("#electric-charger-fast-label-wrapper")
+ .attr("data-tooltip", Utils.translate("electricInterface.outOfStock"))
+ .attr("data-tooltip-location", "top");
+ $("#charger-type-fast").prop("disabled", true);
+ } else {
+ $("#electric-charger-fast-label-wrapper")
+ .removeAttr("data-tooltip")
+ .removeAttr("data-tooltip-location");
+ $("#charger-type-fast").prop("disabled", false);
+ }
+
+ if (currentPumpData.stationStock.electricnormal == 0) {
+ $("#electric-charger-normal-label-wrapper")
+ .attr("data-tooltip", Utils.translate("electricInterface.outOfStock"))
+ .attr("data-tooltip-location", "top");
+ $("#charger-type-normal").prop("disabled", true);
+ } else {
+ $("#electric-charger-normal-label-wrapper")
+ .removeAttr("data-tooltip")
+ .removeAttr("data-tooltip-location");
+ $("#charger-type-normal").prop("disabled", false);
+ }
+
+ $(".electric-charger-type-container").css("display", "");
+ $(".electric-charger-amount-container").css("display", "none");
+ $(".electric-charger-payment-container").css("display", "none");
+ $("#electric-charger-container").fadeIn(200);
+ } else {
+ if (currentPumpData.pumpModel == "prop_gas_pump_1a" || currentPumpData.pumpModel == "prop_gas_pump_1b" || currentPumpData.pumpModel == "prop_gas_pump_1c" || currentPumpData.pumpModel == "prop_gas_pump_1d") {
+ $("#gas-pump-container-image").attr("src", `images/${currentPumpData.pumpModel}.png`);
+ } else {
+ $("#gas-pump-container-image").attr("src", `images/prop_gas_pump_1b.png`);
+ }
+ fuelTypeWarnSent = false;
+ changeSelectedFuelType(currentPumpData.currentFuelType);
+ $(".vehicle-fuel").text(Utils.translate("pumpInterface.vehicleFuel").format(`${Utils.numberFormat(currentPumpData.vehicleFuel, 1)} / ${Utils.numberFormat(currentPumpData.vehicleTankSize, 0)}`));
+ $(".vehicle-fuel").attr("data-tooltip", Utils.translate("pumpInterface.vehicleFuelTooltip"));
+ $(".bank-balance").text(Utils.currencyFormat(currentPumpData.bankBalance, 2));
+ $(".cash-balance").text(Utils.currencyFormat(currentPumpData.cashBalance, 2));
+
+ $(".fuel-type-button.regular").text(Utils.translate("pumpInterface.fuelTypes.regular"));
+ $(".fuel-type-button.plus").text(Utils.translate("pumpInterface.fuelTypes.plus"));
+ $(".fuel-type-button.premium").text(Utils.translate("pumpInterface.fuelTypes.premium"));
+ $(".fuel-type-button.diesel").text(Utils.translate("pumpInterface.fuelTypes.diesel"));
+ $(".confirm-button").text(Utils.translate("pumpInterface.confirm"));
+
+ $("#confirm-refuel-payment-modal-title").text(Utils.translate("confirmRefuelModal.title"));
+ $("#confirm-refuel-payment-modal-pay-bank").text(Utils.translate("confirmRefuelModal.paymentBank"));
+ $("#confirm-refuel-payment-modal-pay-cash").text(Utils.translate("confirmRefuelModal.paymentCash"));
+
+ $("#confirm-jerry-can-payment-modal-title").text(Utils.translate("confirmBuyJerryCanModal.title"));
+ $("#confirm-jerry-can-payment-modal-desc").text(Utils.currencyFormat(currentPumpData.jerryCan.price, 2));
+ $("#confirm-jerry-can-payment-modal-pay-bank").text(Utils.translate("confirmBuyJerryCanModal.paymentBank"));
+ $("#confirm-jerry-can-payment-modal-pay-cash").text(Utils.translate("confirmBuyJerryCanModal.paymentCash"));
+
+ $("#confirm-fuel-type-modal-title").text(Utils.translate("confirmFuelChangeModal.title"));
+ $("#confirm-fuel-type-modal-desc").text(Utils.translate("confirmFuelChangeModal.description"));
+ $("#confirm-fuel-type-modal-confirm").text(Utils.translate("confirmation_modal_confirm_button"));
+ $("#confirm-fuel-type-modal-cancel").text(Utils.translate("confirmation_modal_cancel_button"));
+
+ if (!currentPumpData.jerryCan.enabled) {
+ $(".gas-pump-interactive-button").css("display", "none");
+ }
+
+ updateFuelAmountDisplay(true);
+
+ $("#gas-pump-container").fadeIn(200);
+ }
+ }
+ if (item.hideMainUI) {
+ $("#gas-pump-container").fadeOut(200);
+ $("#electric-charger-container").fadeOut(200);
+ }
+ if (item.showRefuelDisplay) {
+ if (item.isElectric) {
+ let percentageOfTankFilled = (item.currentDisplayFuelAmount / item.currentVehicleTankSize) * 100;
+ $("#recharge-display-title").text(Utils.translate("rechargerDisplay.title"));
+ $("#recharge-display-battery-level-span").text(`${Utils.numberFormat(percentageOfTankFilled, 0)}%`);
+ $("#recharge-display-battery-liquid").css("width", `${percentageOfTankFilled}%`);
+ $("#recharge-display-remaining-time-title").text(Utils.translate("rechargerDisplay.remainingTimeText"));
+ updateRechargeDisplay((item.currentVehicleTankSize - item.currentDisplayFuelAmount), item.fuelTypePurchased);
+ $("#recharge-display").fadeIn(200);
+ } else {
+ $("#refuel-display-pump-value").text(Utils.numberFormat(item.remainingFuelAmount, 2));
+ $("#refuel-display-car-value").text(`${Utils.numberFormat(item.currentDisplayFuelAmount, 2)}/${Utils.numberFormat(item.currentVehicleTankSize, 2)}`);
+ $(".refuel-display-liters").text(Utils.translate("pumpRefuelDisplay.liters"));
+ $("#refuel-display-car-label").text(Utils.translate("pumpRefuelDisplay.carTank"));
+ $("#refuel-display-pump-label").text(Utils.translate("pumpRefuelDisplay.remaining"));
+ $("#refuel-display").fadeIn(200);
+ }
+ }
+ if (item.hideRefuelDisplay) {
+ $("#refuel-display").fadeOut(200);
+ $("#recharge-display").fadeOut(200);
+ }
+ if (item.showFuelConsumptionChart) {
+ toggleChartFocusShortcut = item.focusShortcut;
+ isRecording = item.isRecording;
+
+ createFuelConsumptionChartObject();
+ openFuelConsumptionChart();
+ setFuelConsumptionChartPosition(item.position);
+ updateFuelConsumptionChart({ fuel: null, speed: null, consumption: null });
+ }
+ if (item.updateFuelConsumptionChart) {
+ updateFuelConsumptionChart(item.fuelConsumptionData);
+ }
+ if (item.hideFuelConsumptionChart) {
+ updateFuelConsumptionChart({ fuel: null, speed: null, consumption: null });
+ $("#chart-dialog").fadeOut();
+ // fuelChart.destroy();
+ // speedChart.destroy();
+ // consumptionChart.destroy();
+ }
+});
+
+function updateRechargeDisplay(remainingFuelAmount, chargerType) {
+ if (chargerType == "electricfast") chargerType = "fast";
+ if (chargerType == "electricnormal") chargerType = "normal";
+ if (chargerType && (chargerType === "fast" || chargerType === "normal")) {
+ // Calculate the time to recharge based on remaining fuel amount and charger type's time per unit
+ let timeToRecharge = remainingFuelAmount * currentPumpData.electric.chargeTypes[chargerType].time;
+
+ // Convert time to minutes and seconds
+ let timeToRechargeMinutes = Math.floor(timeToRecharge / 60);
+ let timeToRechargeSeconds = timeToRecharge % 60;
+
+ // Update the display with calculated time
+ $("#recharge-display-remaining-time-value").text(Utils.translate("rechargerDisplay.remainingTimeValue").format(Utils.numberFormat(timeToRechargeMinutes, 0), Utils.numberFormat(timeToRechargeSeconds, 0)));
+ } else {
+ console.log("Invalid charger type or no charger type selected");
+ }
+}
+
+/*=================
+ FUNCTIONS
+=================*/
+
+function changeSelectedFuelType(fuelType) {
+ if (fuelType == "regular" || fuelType == "plus" || fuelType == "premium" || fuelType == "diesel") {
+ $(".fuel-type-button").removeClass("selected");
+ $(`.fuel-type-button.${fuelType}`).addClass("selected");
+
+ $(".price-per-liter").text(Utils.currencyFormat(currentPumpData.pricePerLiter[fuelType], 2));
+ $(".station-stock").text(Utils.translate("pumpInterface.stationStock").format(Utils.numberFormat(currentPumpData.stationStock[fuelType])));
+ selectedFuelType = fuelType;
+ } else {
+ console.log("Invalid fuel type chosen: " + fuelType);
+ }
+}
+
+// Show the modal when confirmRefuel is called
+function confirmRefuel() {
+ if (fuelTypeWarnSent == false && currentPumpData.currentFuelType != selectedFuelType && currentPumpData.vehicleFuel > 0) {
+ fuelTypeWarnSent = true;
+ $("#confirm-fuel-type-modal").fadeIn();
+ } else {
+ let $input = $("#input-fuel-amount");
+ let fuelAmount = parseInt($input.val());
+ $("#confirm-refuel-payment-modal-desc").text(Utils.translate("confirmRefuelModal.description").format(fuelAmount, Utils.translate("pumpInterface.fuelTypes."+selectedFuelType), Utils.currencyFormat(fuelAmount * currentPumpData.pricePerLiter[selectedFuelType])));
+ $("#confirm-refuel-payment-modal").fadeIn();
+ }
+}
+
+// Empty vehicle's tank after user confirm fuel type change
+function changeVehicleFuelType() {
+ closeModal();
+ Utils.post("changeVehicleFuelType", { selectedFuelType });
+ currentPumpData.vehicleFuel = 0;
+ $(".vehicle-fuel").text(Utils.translate("pumpInterface.vehicleFuel").format(Utils.numberFormat(currentPumpData.vehicleFuel, 2)));
+}
+
+// Confirm the buy jerry can action
+function openBuyJerryCanModal() {
+ closeModal();
+ $("#confirm-jerry-can-payment-modal").fadeIn();
+}
+
+// Hide the modal
+function closeModal() {
+ $(".modal").fadeOut();
+}
+
+function confirmRefuelPayment(paymentMethod) {
+ let $input = $("#input-fuel-amount");
+ let fuelAmount = parseInt($input.val());
+ Utils.post("confirmRefuel", { selectedFuelType, fuelAmount, paymentMethod });
+ closeModal();
+}
+
+function confirmJerryCanPayment(paymentMethod) {
+ Utils.post("confirmJerryCanPurchase", { paymentMethod });
+ closeModal();
+}
+
+function increaseZoom() {
+ // Get the current zoom level
+ let currentZoom = parseFloat($("#gas-pump-container").css("zoom")) || 1;
+
+ // Increase zoom by 5%
+ let newZoom = currentZoom + 0.05;
+
+ // Limit the zoom to a maximum of 1.4 (140%)
+ if (newZoom > 1.4) {
+ newZoom = 1.4;
+ }
+
+ // Apply the new zoom level
+ $("#gas-pump-container").css("zoom", newZoom);
+}
+
+function decreaseZoom() {
+ // Get the current zoom level
+ let currentZoom = parseFloat($("#gas-pump-container").css("zoom")) || 1;
+
+ // Decrease zoom by 5%
+ let newZoom = currentZoom - 0.05;
+
+ // Limit the zoom to a minimum of 0.8 (80%)
+ if (newZoom < 0.8) {
+ newZoom = 0.8;
+ }
+
+ // Apply the new zoom level
+ $("#gas-pump-container").css("zoom", newZoom);
+}
+
+// Function to update the display with the 'L' suffix
+function updateFuelAmountDisplay(setToMax = false) {
+ let $input = $("#input-fuel-amount");
+ let value = parseInt($input.val());
+
+ // Set value to 1 if it's not a positive number
+ if (isNaN(value) || value <= 0) {
+ value = 1;
+ }
+
+ // Don't let it purchase more L than the vehicle can hold in the tank
+ if (setToMax || (!isNaN(value) && value > currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
+ value = Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel);
+ }
+
+ $input.val(value + " L");
+}
+
+// Pagination for electric chargers
+function chargerTypeContinue() {
+ let chargerType = getSelectedChargerType();
+ if (chargerType && (chargerType == "fast" || chargerType == "normal")) {
+ $("#electric-charger-amount-input").val(Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel));
+ calculateTimeToRecharge();
+ $("#electric-charger-amount-type-selected").text(Utils.translate("electricInterface.chargerAmount.typeSelected").format(Utils.translate(`electricInterface.chargerType.${chargerType}.title`)));
+ $(".electric-charger-type-container").css("display", "none");
+ $(".electric-charger-amount-container").css("display", "");
+ }
+}
+
+function chargerAmountContinue() {
+ let $input = $("#electric-charger-amount-input");
+ let currentValue = parseInt($input.val()) || 0;
+ let newWidthPercentage = ((currentPumpData.vehicleFuel / currentPumpData.vehicleTankSize) * 100) + ((currentValue / currentPumpData.vehicleTankSize) * 100);
+
+ if (currentValue <= 0 || newWidthPercentage > 100) {
+ return;
+ }
+
+ let chargerType = getSelectedChargerType();
+ $("#electric-charger-pay-button").text(Utils.translate("electricInterface.chargerPayment.payButton").format(Utils.currencyFormat(currentValue * currentPumpData.pricePerLiter["electric"+chargerType], 2)));
+ $(".electric-charger-amount-container").css("display", "none");
+ $(".electric-charger-payment-container").css("display", "");
+}
+
+function chargerAmountReturn() {
+ $(".electric-charger-type-container").css("display", "");
+ $(".electric-charger-amount-container").css("display", "none");
+ $(".electric-charger-payment-container").css("display", "none");
+}
+
+function confirmRecharge() {
+ let $input = $("#electric-charger-amount-input");
+ let fuelAmount = parseInt($input.val()) || 0;
+ Utils.post("confirmRefuel", { selectedFuelType: "electric" + getSelectedChargerType(), fuelAmount, paymentMethod: getSelectedElectricPaymentMethod() });
+}
+
+function chargerPaymentReturn() {
+ $(".electric-charger-type-container").css("display", "none");
+ $(".electric-charger-amount-container").css("display", "");
+ $(".electric-charger-payment-container").css("display", "none");
+}
+
+function getSelectedChargerType() {
+ const selectedInput = $("input[name='charger-type']:checked");
+ return selectedInput.length && !selectedInput.prop("disabled") ? selectedInput.val() : null;
+}
+
+function getSelectedElectricPaymentMethod() {
+ const selectedInput = $("input[name='charger-payment']:checked");
+ return selectedInput.length ? selectedInput.val() : null;
+}
+
+function calculateTimeToRecharge() {
+ let $input = $("#electric-charger-amount-input");
+ let currentValue = parseInt($input.val());
+
+ // Allow empty input temporarily; validate only non-empty values
+ if ($input.val().trim() === "" || isNaN(currentValue) || currentValue <= 0) {
+ currentValue = 0;
+ }
+
+ if (currentValue > 1000) {
+ currentValue = 1000;
+ $input.val(currentValue);
+ }
+
+ let chargerType = getSelectedChargerType();
+ if (chargerType && (chargerType == "fast" || chargerType == "normal")) {
+ let timeToRecharge = currentValue * currentPumpData.electric.chargeTypes[chargerType].time;
+
+ // Calculate minutes and seconds
+ let timeToRechargeMinutes = Math.floor(timeToRecharge / 60);
+ let timeToRechargeSeconds = timeToRecharge % 60;
+
+ $("#electric-time-to-recharge-value").text(Utils.translate("electricInterface.chargerAmount.timeToRechargeValue").format(Utils.numberFormat(timeToRechargeMinutes, 0), Utils.numberFormat(timeToRechargeSeconds, 0)));
+
+ let newWidthPercentage = ((currentPumpData.vehicleFuel / currentPumpData.vehicleTankSize) * 100) + ((currentValue / currentPumpData.vehicleTankSize) * 100);
+ $("#electric-amount-progress-bar").css("width", newWidthPercentage + "%");
+
+ if (newWidthPercentage > 100) {
+ $("#electric-amount-progress-bar").css("background", "red");
+ } else {
+ $("#electric-amount-progress-bar").css("background", "");
+ }
+ } else {
+ console.log("No charger type selected");
+ }
+}
+
+/*===================
+ CHART DIALOG
+===================*/
+
+function openFuelConsumptionChart() {
+ const $dialog = $("#chart-dialog");
+
+ $("#chart-dialog-title").text(Utils.translate("fuelConsumptionChart.title"));
+ $("#chart-dialog-footer-text").text(Utils.translate("fuelConsumptionChart.footer.focus"));
+ $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
+ $("#start-stop-recording-label").text(Utils.translate("fuelConsumptionChart.footer.toggleRecording"));
+ $("#start-stop-recording").prop("checked", isRecording);
+
+ $dialog.css({
+ right: "",
+ bottom: "",
+ display: "flex",
+ }).fadeIn();
+
+ $dialog.draggable({
+ handle: ".dialog-header",
+ }).resizable({
+ minHeight: 450,
+ minWidth: 300,
+ maxHeight: $(window).height()*0.8,
+ maxWidth: $(window).width()*0.8,
+ });
+ speedChart.resize();
+ consumptionChart.resize();
+ fuelChart.resize();
+}
+
+function setFuelConsumptionChartPosition(position) {
+ const $dialog = $("#chart-dialog");
+ const windowWidth = $(window).width();
+ const dialogWidth = $dialog.outerWidth();
+
+ let top = 10;
+ let left;
+
+ // Horizontal position
+ if (position === "left") {
+ left = 10;
+ } else {
+ left = windowWidth - dialogWidth - 10;
+ }
+
+ $dialog.css({
+ top: `${top}px`,
+ left: `${left}px`,
+ });
+}
+
+
+function updateFuelConsumptionChart(latestData) {
+ const now = Date.now();
+
+ if (fuelChart && speedChart && consumptionChart) {
+ fuelChart.data.datasets[0].data.push({ x: now, y: latestData.fuel });
+ speedChart.data.datasets[0].data.push({ x: now, y: latestData.speed });
+ consumptionChart.data.datasets[0].data.push({ x: now, y: latestData.consumption });
+ }
+ fuelChart.update("quiet");
+ speedChart.update("quiet");
+ consumptionChart.update("quiet");
+}
+
+function createFuelConsumptionChartObject() {
+ if (fuelChart || speedChart || consumptionChart) { return; }
+
+ Chart.defaults.color = "rgba(218, 218, 218, 0.73)";
+ Chart.overrides.line.spanGaps = false;
+
+ const baseOptions = {
+ responsive: true,
+ maintainAspectRatio: false,
+ elements: { point: { radius: 0 } },
+ animation: false,
+ interaction: { mode: "index", intersect: false },
+ plugins: {
+ legend: {
+ position: "bottom",
+ labels: { boxWidth: 3, boxHeight: 3 },
+ },
+ streaming: {
+ frameRate: 10,
+ },
+ },
+ scales: {
+ x: {
+ type: "realtime",
+ realtime: {
+ duration: 30000,
+ refresh: 1000,
+ delay: 1000,
+ },
+ },
+ y: {
+ beginAtZero: true,
+ },
+ },
+ };
+
+ // Fuel Chart
+
+ fuelChart = new Chart(document.getElementById("fuel-chart"), {
+ type: "line",
+ data: {
+ datasets: [{
+ label: Utils.translate("fuelConsumptionChart.chartLabels.fuel"),
+ data: [],
+ borderColor: "#FFD800",
+ cubicInterpolationMode: "monotone",
+ }],
+ },
+ options: {
+ ...baseOptions,
+ scales: {
+ ...baseOptions.scales,
+ y: {
+ ...baseOptions.scales.y,
+ suggestedMax: 100,
+ title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.fuel") },
+ },
+ },
+ },
+ });
+
+ // Speed Chart
+
+ speedChart = new Chart(document.getElementById("speed-chart"), {
+ type: "line",
+ data: {
+ datasets: [{
+ label: Utils.translate("fuelConsumptionChart.chartLabels.speed"),
+ data: [],
+ borderColor: "#0026FF",
+ cubicInterpolationMode: "monotone",
+ }],
+ },
+ options: {
+ ...baseOptions,
+ scales: {
+ ...baseOptions.scales,
+ y: {
+ ...baseOptions.scales.y,
+ suggestedMax: 140,
+ title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.speed") },
+ },
+ },
+ },
+ });
+
+ // Consumption Chart
+
+ consumptionChart = new Chart(document.getElementById("consumption-chart"), {
+ type: "line",
+ data: {
+ datasets: [{
+ label: Utils.translate("fuelConsumptionChart.chartLabels.consumption"),
+ data: [],
+ borderColor: "#7F0000",
+ cubicInterpolationMode: "monotone",
+ }],
+ },
+ options: {
+ ...baseOptions,
+ scales: {
+ ...baseOptions.scales,
+ y: {
+ ...baseOptions.scales.y,
+ suggestedMax: 0.3,
+ title: { display: true, text: Utils.translate("fuelConsumptionChart.chartLabels.consumption") },
+ },
+ },
+ },
+ });
+}
+
+
+/*=================
+ LISTENERS
+=================*/
+
+$(window).click(function(event) {
+ // Close the modal when clicking outside of it
+ if ($(event.target).is(".modal")) {
+ closeModal();
+ }
+});
+
+$(document).on("keydown", function(event) {
+ // Handle press of Esc key
+ if (event.key === "Escape" || event.keyCode === 27) {
+ // Check if the modal is open by checking if it's visible
+ if ($("#chart-dialog").is(":visible")) {
+ closeFuelConsumptionChartUI();
+ } else if ($(".modal").is(":visible")) {
+ closeModal();
+ } else {
+ closeUI();
+ }
+ }
+ if (event.key === toggleChartFocusShortcut
+ || event.key === "w" || event.key === "W"
+ || event.key === "a" || event.key === "A"
+ || event.key === "d" || event.key === "D"
+ || event.key === "s" || event.key === "S") {
+ // Check if the modal is open by checking if it's visible
+ if ($("#chart-dialog").is(":visible")) {
+ removeFocusFuelConsumptionChartUI();
+ }
+ }
+});
+
+$(document).ready(function() {
+ // Handle the add button
+ $(".refuel-add").click(function() {
+ let $input = $("#input-fuel-amount");
+ let currentValue = parseInt($input.val()) || 0;
+ if (currentValue < Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
+ $input.val((currentValue + 1) + " L");
+ }
+ });
+ $(".recharge-add").click(function() {
+ let $input = $("#electric-charger-amount-input");
+ let currentValue = parseInt($input.val()) || 0;
+ if (currentValue < Math.floor(currentPumpData.vehicleTankSize - currentPumpData.vehicleFuel)) {
+ $input.val((currentValue + 1));
+ calculateTimeToRecharge();
+ }
+ });
+
+ // Handle the sub button
+ $(".refuel-sub").click(function() {
+ let $input = $("#input-fuel-amount");
+ let currentValue = parseInt($input.val()) || 0;
+ if (currentValue > 1) {
+ $input.val((currentValue - 1) + " L");
+ }
+ });
+ $(".recharge-sub").click(function() {
+ let $input = $("#electric-charger-amount-input");
+ let currentValue = parseInt($input.val()) || 0;
+ if (currentValue > 1) {
+ $input.val((currentValue - 1));
+ calculateTimeToRecharge();
+ }
+ });
+
+ // Remove 'L' suffix on focus to allow numeric input, and add it back on blur
+ $("#input-fuel-amount").on("focus", function() {
+ $(this).val(parseInt($(this).val()) || 1);
+ }).on("blur", function() {
+ updateFuelAmountDisplay();
+ });
+
+ // Recalculate time when change input
+ $("#electric-charger-amount-input").on("input", function() {
+ calculateTimeToRecharge();
+ });
+ $("#electric-charger-amount-input").on("blur", function() {
+ let $input = $(this);
+ let currentValue = parseInt($input.val());
+
+ // If invalid, reset to 0
+ if (isNaN(currentValue) || currentValue <= 0) {
+ $input.val(0);
+ }
+ });
+
+ // Handle chart buttons
+ $("#start-stop-recording").change(function() {
+ if ($(this).is(":checked")) {
+ startRecordingGraph();
+ } else {
+ stopRecordingGraph();
+ }
+ });
+
+ $("#increase-chart-recording").click(function() {
+ if (chartTimestampsIndex < chartTimestamps.length - 1) {
+ chartTimestampsIndex++;
+ $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
+ changeRecordingIndexGraph();
+ }
+ });
+
+ $("#decrease-chart-recording").click(function() {
+ if (chartTimestampsIndex > 0) {
+ chartTimestampsIndex--;
+ $("#stepper-chart-recording-input").text(Utils.translate("fuelConsumptionChart.footer.recordsLength").format(chartTimestamps[chartTimestampsIndex]));
+ changeRecordingIndexGraph();
+ }
+ });
+});
+
+
+/*=================
+ CALLBACKS
+=================*/
+
+function closeUI(){
+ Utils.post("close","");
+}
+
+function stopRecordingGraph(){
+ fuelChart.options.scales.x.realtime.pause = true;
+ speedChart.options.scales.x.realtime.pause = true;
+ consumptionChart.options.scales.x.realtime.pause = true;
+ Utils.post("stopRecordingGraph","");
+}
+
+function startRecordingGraph(){
+ fuelChart.options.scales.x.realtime.pause = false;
+ speedChart.options.scales.x.realtime.pause = false;
+ consumptionChart.options.scales.x.realtime.pause = false;
+ Utils.post("startRecordingGraph","");
+}
+
+function changeRecordingIndexGraph(){
+ fuelChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
+ speedChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
+ consumptionChart.options.scales.x.realtime.duration = chartTimestamps[chartTimestampsIndex] * 1000;
+ Utils.post("changeRecordingIndexGraph",chartTimestampsIndex);
+}
+
+function closeFuelConsumptionChartUI(){
+ Utils.post("closeFuelConsumptionChartUI","");
+}
+
+function removeFocusFuelConsumptionChartUI(){
+ Utils.post("removeFocusFuelConsumptionChartUI","");
}
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/nui/scripts/chartjs-plugin-streaming@2.0.0 b/resources/[carscripts]/lc_fuel/nui/scripts/chartjs-plugin-streaming@2.0.0
index f499cdd0b..3d76e308f 100644
--- a/resources/[carscripts]/lc_fuel/nui/scripts/chartjs-plugin-streaming@2.0.0
+++ b/resources/[carscripts]/lc_fuel/nui/scripts/chartjs-plugin-streaming@2.0.0
@@ -1,7 +1,7 @@
-/*!
- * chartjs-plugin-streaming v2.0.0
- * https://nagix.github.io/chartjs-plugin-streaming
- * (c) 2017-2021 Akihiko Kusanagi
- * Released under the MIT license
- */
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","chart.js/helpers"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).ChartStreaming=t(e.Chart,e.Chart.helpers)}(this,(function(e,t){"use strict";function o(e,t,o){return Math.min(Math.max(e,t),o)}function n(e,o){const n=e.options.realtime,a=e.chart.options.plugins.streaming;return t.valueOrDefault(n[o],a[o])}function a(e,{x:o,y:n},{xAxisID:a,yAxisID:i}){const s={};return t.each(o,(e=>{s[e]={axisId:a}})),t.each(n,(e=>{s[e]={axisId:i}})),s}const i="undefined"==typeof window?t.noop:window.cancelAnimationFrame;function s(e){const t=e.frameRequestID;t&&(i.call(window,t),delete e.frameRequestID)}function r(e){const t=e.refreshTimerID;t&&(clearInterval(t),delete e.refreshTimerID,delete e.refreshInterval)}function l(e,o,n){e.refreshTimerID||(e.refreshTimerID=setInterval((()=>{const n=t.callback(o);e.refreshInterval===n||isNaN(n)||(r(e),l(e,o,n))}),n||0),e.refreshInterval=n||0)}function c(e,o,n){return o="number"==typeof o?o:e.parse(o),t.isFinite(o)?{value:e.getPixelForValue(o),transitionable:!0}:{value:n}}function d(){const t=e.registry.getElement("boxAnnotation"),o=e.registry.getElement("lineAnnotation"),n=e.registry.getElement("pointAnnotation"),a=t.prototype.resolveElementProperties,i=o.prototype.resolveElementProperties,s=n.prototype.resolveElementProperties;t.prototype.resolveElementProperties=function(e,t){return function(e,t,o){const{scales:n,chartArea:a}=t,{xScaleID:i,yScaleID:s,xMin:r,xMax:l,yMin:d,yMax:u}=o,m=n[i],p=n[s],{top:f,left:h,bottom:g,right:y}=a,x=e.$streaming={};if(m){const e=c(m,r,h),t=c(m,l,y),o=e.value>t.value;e.transitionable&&(x[o?"x2":"x"]={axisId:i}),t.transitionable&&(x[o?"x":"x2"]={axisId:i}),e.transitionable!==t.transitionable&&(x.width={axisId:i,reverse:e.transitionable})}if(p){const e=c(p,d,f),t=c(p,u,g),o=e.value>t.value;e.transitionable&&(x[o?"y2":"y"]={axisId:s}),t.transitionable&&(x[o?"y":"y2"]={axisId:s}),e.transitionable!==t.transitionable&&(x.height={axisId:s,reverse:e.transitionable})}}(this,e,t),a.call(this,e,t)},o.prototype.resolveElementProperties=function(e,t){const o=e.chartArea;e.chartArea=function(e,t,o){const{scales:n,chartArea:a}=t,{scaleID:i,value:s}=o,r=n[i],{top:l,left:d,bottom:u,right:m}=a,p=e.$streaming={};if(r){const e=r.isHorizontal();return c(r,s).transitionable&&(p[e?"x":"y"]={axisId:i},p[e?"x2":"y2"]={axisId:i}),e?{top:l,bottom:u}:{left:d,right:m}}const{xScaleID:f,yScaleID:h,xMin:g,xMax:y,yMin:x,yMax:b}=o,v=n[f],I=n[h],D={};if(v){const e=c(v,g),t=c(v,y);e.transitionable?p.x={axisId:f}:D.left=d,t.transitionable?p.x2={axisId:f}:D.right=m}if(I){const e=c(I,x),t=c(I,b);e.transitionable?p.y={axisId:h}:D.top=l,t.transitionable?p.y2={axisId:h}:D.bottom=u}return D}(this,e,t);const n=i.call(this,e,t);return e.chartArea=o,n},n.prototype.resolveElementProperties=function(e,t){return function(e,t,o){const n=t.scales,{xScaleID:a,yScaleID:i,xValue:s,yValue:r}=o,l=n[a],d=n[i],u=e.$streaming={};l&&c(l,s).transitionable&&(u.x={axisId:a});d&&c(d,r).transitionable&&(u.y={axisId:i})}(this,e,t),s.call(this,e,t)}}const u={x:["x","caretX"],y:["y","caretY"]};function m(...e){const t=this,o=t.getActiveElements()[0];if(o){const e=t.chart.getDatasetMeta(o.datasetIndex);t.$streaming=a(0,u,e)}else t.$streaming={};t.constructor.prototype.update.call(t,...e)}const p=new WeakMap;function f(e){const{originalScaleOptions:o}=function(e){let t=p.get(e);return t||(t={originalScaleOptions:{}},p.set(e,t)),t}(e),a=e.scales;return t.each(a,(e=>{const t=e.id;o[t]||(o[t]={duration:n(e,"duration"),delay:n(e,"delay")})})),t.each(o,((e,t)=>{a[t]||delete o[t]})),o}function h(e,t,a,i){const{chart:s,axis:r}=e,{minDuration:l=0,maxDuration:c=1/0,minDelay:d=-1/0,maxDelay:u=1/0}=i&&i[r]||{},m=e.options.realtime,p=n(e,"duration"),h=n(e,"delay"),g=o(p*(2-t),l,c);let y,x;return f(s),y=e.isHorizontal()?(e.right-a.x)/(e.right-e.left):(e.bottom-a.y)/(e.bottom-e.top),x=h+y*(p-g),m.duration=g,m.delay=o(x,d,u),g!==e.max-e.min}function g(e,t,a){const{chart:i,axis:s}=e,{minDelay:r=-1/0,maxDelay:l=1/0}=a&&a[s]||{},c=n(e,"delay")+(e.getValueForPixel(t)-e.getValueForPixel(0));return f(i),e.options.realtime.delay=o(c,r,l),!0}function y(e,o){const n=o.$streaming;if(n.zoomPlugin!==e){const a=n.resetZoom=o.resetZoom;!function(e){e.zoomFunctions.realtime=h,e.panFunctions.realtime=g}(e),o.resetZoom=e=>{!function(e){const o=f(e);t.each(e.scales,(e=>{const t=e.options.realtime;if(t){const n=o[e.id];n?(t.duration=n.duration,t.delay=n.delay):(delete t.duration,delete t.delay)}}))}(o),a(e)},n.zoomPlugin=e}}function x(e){const t=e.$streaming;t.zoomPlugin&&(e.resetZoom=t.resetZoom,function(e){p.delete(e)}(e),delete t.resetZoom,delete t.zoomPlugin)}const b={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,15,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,15,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},v=Object.keys(b);function I(e,o,n){if(n){if(n.length){const{lo:a,hi:i}=t._lookup(n,o);e[n[a]>=o?n[a]:n[i]]=!0}}else e[o]=!0}const D=["pointBackgroundColor","pointBorderColor","pointBorderWidth","pointRadius","pointRotation","pointStyle","pointHitRadius","pointHoverBackgroundColor","pointHoverBorderColor","pointHoverBorderWidth","pointHoverRadius","backgroundColor","borderColor","borderSkipped","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","radius","rotation"];function k(e,o,n){const a=e.$animations||{};t.each(e.$streaming,((i,s)=>{if(i.axisId===o){const o=i.reverse?-n:n,r=a[s];t.isFinite(e[s])&&(e[s]-=o),r&&(r._from-=o,r._to-=o)}}))}class w extends e.TimeScale{constructor(e){super(e),this.$realtime=this.$realtime||{}}init(e,o){const a=this;super.init(e,o),l(a.$realtime,(()=>{const e=a.chart,o=n(a,"onRefresh");return t.callback(o,[e],a),function(e){const{chart:o,id:a,max:i}=e,s=n(e,"duration"),r=n(e,"delay"),l=n(e,"ttl"),c=n(e,"pause"),d=Date.now()-(isNaN(l)?s+r:l);let u,m,p,f;t.each(o.data.datasets,((e,n)=>{const s=o.getDatasetMeta(n),r=a===s.xAxisID?"x":a===s.yAxisID&&"y";if(r){const a=s.controller,h=e.data,g=h.length;if(c){for(u=0;u{t.isArray(e[o])&&e[o].splice(m,p)})),t.each(e.datalabels,(e=>{t.isArray(e)&&e.splice(m,p)})),"object"!=typeof h[0]&&(f={start:m,count:p}),t.each(o._active,((e,t)=>{e.datasetIndex===n&&e.index>=m&&(e.index>=m+p?e.index-=p:o._active.splice(t,1))}),null,!0)}})),f&&o.data.labels.splice(f.start,f.count)}(a),e.update("quiet"),n(a,"refresh")}))}update(e,o,a){const i=this,{$realtime:r,options:l}=i,{bounds:c,offset:d,ticks:u}=l,{autoSkip:m,source:p,major:f}=u,h=f.enabled;n(i,"pause")?s(r):(r.frameRequestID||(r.head=Date.now()),function(e,o){if(!e.frameRequestID){const n=()=>{const a=e.nextRefresh||0,i=Date.now();if(a<=i){const n=t.callback(o),a=1e3/(Math.max(n,0)||30),s=e.nextRefresh+a||0;e.nextRefresh=s>i?s:i+a}e.frameRequestID=t.requestAnimFrame.call(window,n)};e.frameRequestID=t.requestAnimFrame.call(window,n)}}(r,(()=>{const e=i.chart,o=e.$streaming;return function(e){const{chart:o,id:a,$realtime:i}=e,s=n(e,"duration"),r=n(e,"delay"),l=e.isHorizontal(),c=l?e.width:e.height,d=Date.now(),u=o.tooltip,m=function(e){const t=e.$streaming.annotationPlugin;if(t){const o=t._getState(e);return o&&o.elements||[]}return[]}(o);let p=c*(d-i.head)/s;l===!!e.options.reverse&&(p=-p),t.each(o.data.datasets,((e,t)=>{const n=o.getDatasetMeta(t),{data:i=[],dataset:s}=n;for(let e=0,t=i.length;el.shift(),set:t.noop}),Object.defineProperty(e,"max",{get:()=>r.shift(),set:t.noop});const c=super.buildTicks();return delete e.min,delete e.max,e.min=s,e.max=i,c}calculateLabelRotation(){const e=this.options.ticks,t=e.maxRotation;e.maxRotation=e.minRotation||0,super.calculateLabelRotation(),e.maxRotation=t}fit(){const e=this,t=e.options;super.fit(),t.ticks.display&&t.display&&e.isHorizontal()&&(e.paddingLeft=3,e.paddingRight=3,e._handleMargins())}draw(e){const o=this,{chart:n,ctx:a}=o,i=o.isHorizontal()?{left:e.left,top:0,right:e.right,bottom:n.height}:{left:0,top:e.top,right:n.width,bottom:e.bottom};o._gridLineItems=null,o._labelItems=null,t.clipArea(a,i),super.draw(e),t.unclipArea(a)}destroy(){const e=this.$realtime;s(e),r(e)}_generate(){const e=this,o=e._adapter,a=n(e,"duration"),i=n(e,"delay"),s=n(e,"refresh"),r=e.$realtime.head-i,l=r-a,c=e._getLabelCapacity(l),{time:d,ticks:u}=e.options,m=d.unit||function(e,t,o,n){const a=o-t,i=v.length;for(let t=v.indexOf(e);t1e5*f)throw new Error(l+" and "+r+" are too far apart with stepSize of "+f+" "+m);k=R,g&&p&&!y&&!d.round&&(k=+o.startOf(k,p),k=+o.add(k,~~((R-k)/(x.size*f))*f,m));const $="data"===u.source&&e.getDataTimestamps();for(w=0;ke-t)).map((e=>+e))}}w.id="realtime",w.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},realtime:{},ticks:{autoSkip:!1,source:"auto",major:{enabled:!0}}},e.defaults.describe("scale.realtime",{_scriptable:e=>"onRefresh"!==e});e.defaults.set("transitions",{quiet:{animation:{duration:0}}});const R={x:["x","cp1x","cp2x"],y:["y","cp1y","cp2y"]};function $(o){const n=this;"quiet"===o&&t.each(n.data.datasets,((t,o)=>{n.getDatasetMeta(o).controller._setStyle=function(t,o,n,a){e.DatasetController.prototype._setStyle.call(this,t,o,"quiet",a)}})),e.Chart.prototype.update.call(n,o),"quiet"===o&&t.each(n.data.datasets,((e,t)=>{delete n.getDatasetMeta(t).controller._setStyle}))}function E(e){const t=e.$streaming;e.render(),t.lastMouseEvent&&setTimeout((()=>{const o=t.lastMouseEvent;o&&e._eventHandler(o)}),0)}const M=[{id:"streaming",version:"2.0.0",beforeInit(e){const o=e.$streaming=e.$streaming||{render:E},n=o.canvas=e.canvas,a=o.mouseEventListener=n=>{const a=t.getRelativePosition(n,e);o.lastMouseEvent={type:"mousemove",chart:e,native:n,x:a.x,y:a.y}};n.addEventListener("mousedown",a),n.addEventListener("mouseup",a)},afterInit(e){e.update=$},beforeUpdate(o){const{scales:n,elements:a}=o.options,i=o.tooltip;t.each(n,(({type:e})=>{"realtime"===e&&(a.line.capBezierPoints=!1)})),i&&(i.update=m);try{!function(e,t){const o=t.$streaming;if(o.annotationPlugin!==e){const t=e.afterUpdate;d(),o.annotationPlugin=e,e.afterUpdate=(e,o,n)=>{const a=o.mode,i=n.animation;"quiet"===a&&(n.animation=!1),t.call(this,e,o,n),"quiet"===a&&(n.animation=i)}}}(e.registry.getPlugin("annotation"),o)}catch(e){!function(e){delete e.$streaming.annotationPlugin}(o)}try{y(e.registry.getPlugin("zoom"),o)}catch(e){x(o)}},beforeDatasetUpdate(e,o){const{meta:n,mode:a}=o;if("quiet"===a){const{controller:e,$animations:o}=n;o&&o.visible&&o.visible._active&&(e.updateElement=t.noop,e.updateSharedOptions=t.noop)}},afterDatasetUpdate(e,t){const{meta:o,mode:n}=t,{data:i=[],dataset:s,controller:r}=o;for(let e=0,t=i.length;e{e instanceof w&&e.destroy()}))},defaults:{duration:1e4,delay:0,frameRate:30,refresh:1e3,onRefresh:null,pause:!1,ttl:void 0},descriptors:{_scriptable:e=>"onRefresh"!==e}},w];return e.Chart.register(M),M}));
+/*!
+ * chartjs-plugin-streaming v2.0.0
+ * https://nagix.github.io/chartjs-plugin-streaming
+ * (c) 2017-2021 Akihiko Kusanagi
+ * Released under the MIT license
+ */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","chart.js/helpers"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).ChartStreaming=t(e.Chart,e.Chart.helpers)}(this,(function(e,t){"use strict";function o(e,t,o){return Math.min(Math.max(e,t),o)}function n(e,o){const n=e.options.realtime,a=e.chart.options.plugins.streaming;return t.valueOrDefault(n[o],a[o])}function a(e,{x:o,y:n},{xAxisID:a,yAxisID:i}){const s={};return t.each(o,(e=>{s[e]={axisId:a}})),t.each(n,(e=>{s[e]={axisId:i}})),s}const i="undefined"==typeof window?t.noop:window.cancelAnimationFrame;function s(e){const t=e.frameRequestID;t&&(i.call(window,t),delete e.frameRequestID)}function r(e){const t=e.refreshTimerID;t&&(clearInterval(t),delete e.refreshTimerID,delete e.refreshInterval)}function l(e,o,n){e.refreshTimerID||(e.refreshTimerID=setInterval((()=>{const n=t.callback(o);e.refreshInterval===n||isNaN(n)||(r(e),l(e,o,n))}),n||0),e.refreshInterval=n||0)}function c(e,o,n){return o="number"==typeof o?o:e.parse(o),t.isFinite(o)?{value:e.getPixelForValue(o),transitionable:!0}:{value:n}}function d(){const t=e.registry.getElement("boxAnnotation"),o=e.registry.getElement("lineAnnotation"),n=e.registry.getElement("pointAnnotation"),a=t.prototype.resolveElementProperties,i=o.prototype.resolveElementProperties,s=n.prototype.resolveElementProperties;t.prototype.resolveElementProperties=function(e,t){return function(e,t,o){const{scales:n,chartArea:a}=t,{xScaleID:i,yScaleID:s,xMin:r,xMax:l,yMin:d,yMax:u}=o,m=n[i],p=n[s],{top:f,left:h,bottom:g,right:y}=a,x=e.$streaming={};if(m){const e=c(m,r,h),t=c(m,l,y),o=e.value>t.value;e.transitionable&&(x[o?"x2":"x"]={axisId:i}),t.transitionable&&(x[o?"x":"x2"]={axisId:i}),e.transitionable!==t.transitionable&&(x.width={axisId:i,reverse:e.transitionable})}if(p){const e=c(p,d,f),t=c(p,u,g),o=e.value>t.value;e.transitionable&&(x[o?"y2":"y"]={axisId:s}),t.transitionable&&(x[o?"y":"y2"]={axisId:s}),e.transitionable!==t.transitionable&&(x.height={axisId:s,reverse:e.transitionable})}}(this,e,t),a.call(this,e,t)},o.prototype.resolveElementProperties=function(e,t){const o=e.chartArea;e.chartArea=function(e,t,o){const{scales:n,chartArea:a}=t,{scaleID:i,value:s}=o,r=n[i],{top:l,left:d,bottom:u,right:m}=a,p=e.$streaming={};if(r){const e=r.isHorizontal();return c(r,s).transitionable&&(p[e?"x":"y"]={axisId:i},p[e?"x2":"y2"]={axisId:i}),e?{top:l,bottom:u}:{left:d,right:m}}const{xScaleID:f,yScaleID:h,xMin:g,xMax:y,yMin:x,yMax:b}=o,v=n[f],I=n[h],D={};if(v){const e=c(v,g),t=c(v,y);e.transitionable?p.x={axisId:f}:D.left=d,t.transitionable?p.x2={axisId:f}:D.right=m}if(I){const e=c(I,x),t=c(I,b);e.transitionable?p.y={axisId:h}:D.top=l,t.transitionable?p.y2={axisId:h}:D.bottom=u}return D}(this,e,t);const n=i.call(this,e,t);return e.chartArea=o,n},n.prototype.resolveElementProperties=function(e,t){return function(e,t,o){const n=t.scales,{xScaleID:a,yScaleID:i,xValue:s,yValue:r}=o,l=n[a],d=n[i],u=e.$streaming={};l&&c(l,s).transitionable&&(u.x={axisId:a});d&&c(d,r).transitionable&&(u.y={axisId:i})}(this,e,t),s.call(this,e,t)}}const u={x:["x","caretX"],y:["y","caretY"]};function m(...e){const t=this,o=t.getActiveElements()[0];if(o){const e=t.chart.getDatasetMeta(o.datasetIndex);t.$streaming=a(0,u,e)}else t.$streaming={};t.constructor.prototype.update.call(t,...e)}const p=new WeakMap;function f(e){const{originalScaleOptions:o}=function(e){let t=p.get(e);return t||(t={originalScaleOptions:{}},p.set(e,t)),t}(e),a=e.scales;return t.each(a,(e=>{const t=e.id;o[t]||(o[t]={duration:n(e,"duration"),delay:n(e,"delay")})})),t.each(o,((e,t)=>{a[t]||delete o[t]})),o}function h(e,t,a,i){const{chart:s,axis:r}=e,{minDuration:l=0,maxDuration:c=1/0,minDelay:d=-1/0,maxDelay:u=1/0}=i&&i[r]||{},m=e.options.realtime,p=n(e,"duration"),h=n(e,"delay"),g=o(p*(2-t),l,c);let y,x;return f(s),y=e.isHorizontal()?(e.right-a.x)/(e.right-e.left):(e.bottom-a.y)/(e.bottom-e.top),x=h+y*(p-g),m.duration=g,m.delay=o(x,d,u),g!==e.max-e.min}function g(e,t,a){const{chart:i,axis:s}=e,{minDelay:r=-1/0,maxDelay:l=1/0}=a&&a[s]||{},c=n(e,"delay")+(e.getValueForPixel(t)-e.getValueForPixel(0));return f(i),e.options.realtime.delay=o(c,r,l),!0}function y(e,o){const n=o.$streaming;if(n.zoomPlugin!==e){const a=n.resetZoom=o.resetZoom;!function(e){e.zoomFunctions.realtime=h,e.panFunctions.realtime=g}(e),o.resetZoom=e=>{!function(e){const o=f(e);t.each(e.scales,(e=>{const t=e.options.realtime;if(t){const n=o[e.id];n?(t.duration=n.duration,t.delay=n.delay):(delete t.duration,delete t.delay)}}))}(o),a(e)},n.zoomPlugin=e}}function x(e){const t=e.$streaming;t.zoomPlugin&&(e.resetZoom=t.resetZoom,function(e){p.delete(e)}(e),delete t.resetZoom,delete t.zoomPlugin)}const b={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,15,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,15,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},v=Object.keys(b);function I(e,o,n){if(n){if(n.length){const{lo:a,hi:i}=t._lookup(n,o);e[n[a]>=o?n[a]:n[i]]=!0}}else e[o]=!0}const D=["pointBackgroundColor","pointBorderColor","pointBorderWidth","pointRadius","pointRotation","pointStyle","pointHitRadius","pointHoverBackgroundColor","pointHoverBorderColor","pointHoverBorderWidth","pointHoverRadius","backgroundColor","borderColor","borderSkipped","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","radius","rotation"];function k(e,o,n){const a=e.$animations||{};t.each(e.$streaming,((i,s)=>{if(i.axisId===o){const o=i.reverse?-n:n,r=a[s];t.isFinite(e[s])&&(e[s]-=o),r&&(r._from-=o,r._to-=o)}}))}class w extends e.TimeScale{constructor(e){super(e),this.$realtime=this.$realtime||{}}init(e,o){const a=this;super.init(e,o),l(a.$realtime,(()=>{const e=a.chart,o=n(a,"onRefresh");return t.callback(o,[e],a),function(e){const{chart:o,id:a,max:i}=e,s=n(e,"duration"),r=n(e,"delay"),l=n(e,"ttl"),c=n(e,"pause"),d=Date.now()-(isNaN(l)?s+r:l);let u,m,p,f;t.each(o.data.datasets,((e,n)=>{const s=o.getDatasetMeta(n),r=a===s.xAxisID?"x":a===s.yAxisID&&"y";if(r){const a=s.controller,h=e.data,g=h.length;if(c){for(u=0;u{t.isArray(e[o])&&e[o].splice(m,p)})),t.each(e.datalabels,(e=>{t.isArray(e)&&e.splice(m,p)})),"object"!=typeof h[0]&&(f={start:m,count:p}),t.each(o._active,((e,t)=>{e.datasetIndex===n&&e.index>=m&&(e.index>=m+p?e.index-=p:o._active.splice(t,1))}),null,!0)}})),f&&o.data.labels.splice(f.start,f.count)}(a),e.update("quiet"),n(a,"refresh")}))}update(e,o,a){const i=this,{$realtime:r,options:l}=i,{bounds:c,offset:d,ticks:u}=l,{autoSkip:m,source:p,major:f}=u,h=f.enabled;n(i,"pause")?s(r):(r.frameRequestID||(r.head=Date.now()),function(e,o){if(!e.frameRequestID){const n=()=>{const a=e.nextRefresh||0,i=Date.now();if(a<=i){const n=t.callback(o),a=1e3/(Math.max(n,0)||30),s=e.nextRefresh+a||0;e.nextRefresh=s>i?s:i+a}e.frameRequestID=t.requestAnimFrame.call(window,n)};e.frameRequestID=t.requestAnimFrame.call(window,n)}}(r,(()=>{const e=i.chart,o=e.$streaming;return function(e){const{chart:o,id:a,$realtime:i}=e,s=n(e,"duration"),r=n(e,"delay"),l=e.isHorizontal(),c=l?e.width:e.height,d=Date.now(),u=o.tooltip,m=function(e){const t=e.$streaming.annotationPlugin;if(t){const o=t._getState(e);return o&&o.elements||[]}return[]}(o);let p=c*(d-i.head)/s;l===!!e.options.reverse&&(p=-p),t.each(o.data.datasets,((e,t)=>{const n=o.getDatasetMeta(t),{data:i=[],dataset:s}=n;for(let e=0,t=i.length;el.shift(),set:t.noop}),Object.defineProperty(e,"max",{get:()=>r.shift(),set:t.noop});const c=super.buildTicks();return delete e.min,delete e.max,e.min=s,e.max=i,c}calculateLabelRotation(){const e=this.options.ticks,t=e.maxRotation;e.maxRotation=e.minRotation||0,super.calculateLabelRotation(),e.maxRotation=t}fit(){const e=this,t=e.options;super.fit(),t.ticks.display&&t.display&&e.isHorizontal()&&(e.paddingLeft=3,e.paddingRight=3,e._handleMargins())}draw(e){const o=this,{chart:n,ctx:a}=o,i=o.isHorizontal()?{left:e.left,top:0,right:e.right,bottom:n.height}:{left:0,top:e.top,right:n.width,bottom:e.bottom};o._gridLineItems=null,o._labelItems=null,t.clipArea(a,i),super.draw(e),t.unclipArea(a)}destroy(){const e=this.$realtime;s(e),r(e)}_generate(){const e=this,o=e._adapter,a=n(e,"duration"),i=n(e,"delay"),s=n(e,"refresh"),r=e.$realtime.head-i,l=r-a,c=e._getLabelCapacity(l),{time:d,ticks:u}=e.options,m=d.unit||function(e,t,o,n){const a=o-t,i=v.length;for(let t=v.indexOf(e);t1e5*f)throw new Error(l+" and "+r+" are too far apart with stepSize of "+f+" "+m);k=R,g&&p&&!y&&!d.round&&(k=+o.startOf(k,p),k=+o.add(k,~~((R-k)/(x.size*f))*f,m));const $="data"===u.source&&e.getDataTimestamps();for(w=0;ke-t)).map((e=>+e))}}w.id="realtime",w.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},realtime:{},ticks:{autoSkip:!1,source:"auto",major:{enabled:!0}}},e.defaults.describe("scale.realtime",{_scriptable:e=>"onRefresh"!==e});e.defaults.set("transitions",{quiet:{animation:{duration:0}}});const R={x:["x","cp1x","cp2x"],y:["y","cp1y","cp2y"]};function $(o){const n=this;"quiet"===o&&t.each(n.data.datasets,((t,o)=>{n.getDatasetMeta(o).controller._setStyle=function(t,o,n,a){e.DatasetController.prototype._setStyle.call(this,t,o,"quiet",a)}})),e.Chart.prototype.update.call(n,o),"quiet"===o&&t.each(n.data.datasets,((e,t)=>{delete n.getDatasetMeta(t).controller._setStyle}))}function E(e){const t=e.$streaming;e.render(),t.lastMouseEvent&&setTimeout((()=>{const o=t.lastMouseEvent;o&&e._eventHandler(o)}),0)}const M=[{id:"streaming",version:"2.0.0",beforeInit(e){const o=e.$streaming=e.$streaming||{render:E},n=o.canvas=e.canvas,a=o.mouseEventListener=n=>{const a=t.getRelativePosition(n,e);o.lastMouseEvent={type:"mousemove",chart:e,native:n,x:a.x,y:a.y}};n.addEventListener("mousedown",a),n.addEventListener("mouseup",a)},afterInit(e){e.update=$},beforeUpdate(o){const{scales:n,elements:a}=o.options,i=o.tooltip;t.each(n,(({type:e})=>{"realtime"===e&&(a.line.capBezierPoints=!1)})),i&&(i.update=m);try{!function(e,t){const o=t.$streaming;if(o.annotationPlugin!==e){const t=e.afterUpdate;d(),o.annotationPlugin=e,e.afterUpdate=(e,o,n)=>{const a=o.mode,i=n.animation;"quiet"===a&&(n.animation=!1),t.call(this,e,o,n),"quiet"===a&&(n.animation=i)}}}(e.registry.getPlugin("annotation"),o)}catch(e){!function(e){delete e.$streaming.annotationPlugin}(o)}try{y(e.registry.getPlugin("zoom"),o)}catch(e){x(o)}},beforeDatasetUpdate(e,o){const{meta:n,mode:a}=o;if("quiet"===a){const{controller:e,$animations:o}=n;o&&o.visible&&o.visible._active&&(e.updateElement=t.noop,e.updateSharedOptions=t.noop)}},afterDatasetUpdate(e,t){const{meta:o,mode:n}=t,{data:i=[],dataset:s,controller:r}=o;for(let e=0,t=i.length;e{e instanceof w&&e.destroy()}))},defaults:{duration:1e4,delay:0,frameRate:30,refresh:1e3,onRefresh:null,pause:!1,ttl:void 0},descriptors:{_scriptable:e=>"onRefresh"!==e}},w];return e.Chart.register(M),M}));
diff --git a/resources/[carscripts]/lc_fuel/nui/ui.html b/resources/[carscripts]/lc_fuel/nui/ui.html
index d17eacf02..79dd2469b 100644
--- a/resources/[carscripts]/lc_fuel/nui/ui.html
+++ b/resources/[carscripts]/lc_fuel/nui/ui.html
@@ -1,279 +1,279 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
×
-
-

-
-
-
-
-
-
-
-
-
-
-
-
×
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
×
+
+

+
+
+
+
+
+
+
+
+
+
+
+
×
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/[carscripts]/lc_fuel/server/server.lua b/resources/[carscripts]/lc_fuel/server/server.lua
index 44eef9155..9642bf60f 100644
--- a/resources/[carscripts]/lc_fuel/server/server.lua
+++ b/resources/[carscripts]/lc_fuel/server/server.lua
@@ -1,579 +1,582 @@
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Versioning
------------------------------------------------------------------------------------------------------------------------------------------
-
-version = ''
-subversion = ''
-api_response = {}
-local utils_required_version = '1.2.1'
-local utils_outdated = false
-
-function checkVersion()
- CreateThread(function()
- local connected = false
- local attempts = 0
- while not connected and attempts < 3 do
- attempts = attempts + 1
-
- PerformHttpRequest("https://raw.githubusercontent.com/LeonardoSoares98/lc_fuel/main/version", function(errorCode, resultData)
- if errorCode == 200 and resultData then
- connected = true
- local latest_version = Utils.Math.trim(resultData)
-
- api_response.latest_version = latest_version
- if Utils.Math.checkIfCurrentVersionisOutdated(latest_version, version) then
- api_response.has_update = true
- print("^4["..GetCurrentResourceName().."] An update is available, download it in https://github.com/LeonardoSoares98/lc_fuel/releases/latest/download/lc_fuel.zip^7 ^3[v"..api_response.latest_version.."]^7")
- else
- api_response.has_update = false
- end
- end
- end, "GET", "", {})
-
- Wait(10000)
- end
- end)
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Script global variables
------------------------------------------------------------------------------------------------------------------------------------------
-
-Utils = Utils or exports['lc_utils']:GetUtils()
-local cooldown = {}
-local playerVehiclesFuelType = {}
-local fuelPurchased = {}
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Script functions
------------------------------------------------------------------------------------------------------------------------------------------
-
-RegisterServerEvent("lc_fuel:serverOpenUI")
-AddEventHandler("lc_fuel:serverOpenUI",function(isElectric, pumpModel, vehicleFuel, vehicleTankSize, vehiclePlate)
- local source = source
- Wrapper(source,function(user_id)
- local gasStationId = getCurrentGasStationId(source)
- serverOpenUI(source, isElectric, pumpModel, gasStationId, vehicleFuel, vehicleTankSize, vehiclePlate)
- end)
-end)
-
-RegisterServerEvent("lc_fuel:confirmRefuel")
-AddEventHandler("lc_fuel:confirmRefuel",function(data)
- local source = source
- Wrapper(source,function(user_id)
- if not data or data.fuelAmount <= 0 or not isFuelTypeValid(data.selectedFuelType) or not isPaymentMethodValid(data.paymentMethod) then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('invalid_value'))
- return
- end
-
- local gasStationId = getCurrentGasStationId(source)
- local stationData = getStationData(gasStationId)
- local pricePerLiter = stationData.pricePerLiter[data.selectedFuelType]
- local initialPrice = pricePerLiter * data.fuelAmount
-
- local discount = getPlayerDiscountAmount(source)
- local finalPrice = initialPrice * (1 - (discount / 100))
- if Utils.Framework.getPlayerAccountMoney(source, Config.Accounts[data.paymentMethod]) < finalPrice then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_money'):format(Utils.numberFormat(finalPrice)))
- return
- end
-
- if not removeStockFromStation(gasStationId, finalPrice, data.fuelAmount, data.selectedFuelType, false) then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
- return
- end
-
- Utils.Framework.tryRemoveAccountMoney(source, finalPrice, Config.Accounts[data.paymentMethod])
-
- fuelPurchased[source] = {
- finalPrice = finalPrice,
- account = Config.Accounts[data.paymentMethod],
- selectedFuelType = data.selectedFuelType,
- fuelAmount = data.fuelAmount,
- pricePerLiter = pricePerLiter,
- }
-
- TriggerClientEvent("lc_fuel:getPumpNozzle", source, data.fuelAmount, data.selectedFuelType)
- TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('refuel_paid'):format(Utils.numberFormat(finalPrice)))
- end)
-end)
-
-
-RegisterServerEvent("lc_fuel:returnNozzle")
-AddEventHandler("lc_fuel:returnNozzle",function(remainingFuel, isElectric)
- local source = source
- Wrapper(source,function(user_id)
-
- if not Config.ReturnNozzleRefund then
- return
- end
-
- if not fuelPurchased[source] then
- return
- end
-
- if remainingFuel < 1 then
- fuelPurchased[source] = nil
- return
- end
-
- local discount = getPlayerDiscountAmount(source)
- local amountToReturn = math.floor(remainingFuel * (fuelPurchased[source].pricePerLiter * (1 - (discount / 100))))
-
- if amountToReturn > fuelPurchased[source].finalPrice or remainingFuel > fuelPurchased[source].fuelAmount then
- print("User "..user_id.." initially purchased "..fuelPurchased[source].fuelAmount.."L of fuel but now is returning "..remainingFuel.."L. Is this user trying to glitch something?")
- print("User coords: "..GetEntityCoords(GetPlayerPed(source)))
- fuelPurchased[source] = nil
- return
- end
-
- local gasStationId = getCurrentGasStationId(source)
- local _, returnedAmount = returnStockToGasStation(gasStationId, amountToReturn, remainingFuel, fuelPurchased[source].selectedFuelType)
-
- if isElectric then
- TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('returned_charge'):format(Utils.Math.round(remainingFuel, 1), returnedAmount))
- else
- TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('returned_fuel'):format(Utils.Math.round(remainingFuel, 1), returnedAmount))
- end
- Utils.Framework.giveAccountMoney(source, returnedAmount, fuelPurchased[source].account)
-
- fuelPurchased[source] = nil
- end)
-end)
-
-RegisterServerEvent("lc_fuel:confirmJerryCanPurchase")
-AddEventHandler("lc_fuel:confirmJerryCanPurchase",function(data)
- if not Config.JerryCan.enabled then return end
- local source = source
- Wrapper(source,function(user_id)
- if not isPaymentMethodValid(data.paymentMethod) then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('invalid_value'))
- return
- end
-
- local gasStationId = getCurrentGasStationId(source)
- local stationData = getStationData(gasStationId)
- local fuelType = nil
- -- Check which type has enough stock
- if stationData.stationStock.regular >= Config.JerryCan.requiredStock then
- fuelType = "regular"
- elseif stationData.stationStock.plus >= Config.JerryCan.requiredStock then
- fuelType = "plus"
- elseif stationData.stationStock.premium >= Config.JerryCan.requiredStock then
- fuelType = "premium"
- elseif stationData.stationStock.diesel >= Config.JerryCan.requiredStock then
- fuelType = "diesel"
- end
-
- if fuelType == nil then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
- return
- end
-
- if Utils.Framework.getPlayerAccountMoney(source, Config.Accounts[data.paymentMethod]) < Config.JerryCan.price then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_money'):format(Config.JerryCan.price))
- return
- end
-
- if not removeStockFromStation(gasStationId, Config.JerryCan.price, Config.JerryCan.requiredStock, fuelType, true) then
- TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
- return
- end
- Utils.Framework.tryRemoveAccountMoney(source, Config.JerryCan.price, Config.Accounts[data.paymentMethod])
-
- -- Gives the jerry can to the player
- if Config.JerryCan.giveAsWeapon then
- Utils.Framework.givePlayerWeapon(source, Config.JerryCan.item, 1, Config.JerryCan.metadata)
- else
- Utils.Framework.givePlayerItem(source, Config.JerryCan.item, 1, Config.JerryCan.metadata)
- end
-
- TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('jerry_can_paid'):format(Config.JerryCan.price))
- TriggerClientEvent("lc_fuel:closeUI", source, data.fuelAmount, data.selectedFuelType)
- end)
-end)
-
-function serverOpenUI(source, isElectric, pumpModel, gasStationId, vehicleFuel, vehicleTankSize, vehiclePlate)
- local stationData = getStationData(gasStationId)
- local discount = getPlayerDiscountAmount(source)
-
- local data = {
- pricePerLiter = stationData.pricePerLiter,
- stationStock = stationData.stationStock,
- currentFuelType = getVehicleFuelType(vehiclePlate),
- vehicleFuel = vehicleFuel or 0,
- vehicleTankSize = vehicleTankSize or 100,
- cashBalance = Utils.Framework.getPlayerAccountMoney(source, Config.Accounts.account1),
- bankBalance = Utils.Framework.getPlayerAccountMoney(source, Config.Accounts.account2),
- jerryCan = Config.JerryCan,
- isElectric = isElectric,
- electric = Config.Electric,
- pumpModel = pumpModel,
- }
-
- -- Apply the discount to each fuel type price based on player job
- for fuelType, price in pairs(stationData.pricePerLiter) do
- data.pricePerLiter[fuelType] = price * (1 - (discount / 100))
- end
-
- TriggerClientEvent("lc_fuel:clientOpenUI", source, data)
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Gas Station stock functions
------------------------------------------------------------------------------------------------------------------------------------------
-
-function getCurrentGasStationId(source)
- if not Config.PlayerOwnedGasStations.enabled then return nil end
- local playerCoords = GetEntityCoords(GetPlayerPed(source))
- for k,v in pairs(Config.PlayerOwnedGasStations.gasStations) do
- if #(v.vector - playerCoords) <= v.radius then
- return k
- end
- end
- return nil
-end
-
-function getStationData(gasStationId)
- local stationData = getStationDataFromConfig()
- if not gasStationId then
- return stationData
- end
-
- local sql = "SELECT price, stock, price_plus, stock_plus, price_premium, stock_premium, price_diesel, stock_diesel, price_electricfast, stock_electricfast, price_electricnormal, stock_electricnormal FROM gas_station_business WHERE gas_station_id = @gas_station_id";
- local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
-
- if not query then
- return stationData
- end
-
- local sql = "UPDATE `gas_station_business` SET total_visits = total_visits + 1 WHERE gas_station_id = @gas_station_id";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId});
-
- stationData = {
- pricePerLiter = {
- regular = query.price/100,
- plus = query.price_plus/100,
- premium = query.price_premium/100,
- diesel = query.price_diesel/100,
- electricfast = query.price_electricfast/100,
- electricnormal = query.price_electricnormal/100,
- },
- stationStock = {
- regular = query.stock,
- plus = query.stock_plus,
- premium = query.stock_premium,
- diesel = query.stock_diesel,
- electricfast = query.stock_electricfast == 1 and 100 or 0,
- electricnormal = query.stock_electricnormal == 1 and 100 or 0,
- }
- }
-
- return stationData
-end
-
-function removeStockFromStation(gasStationId, pricePaid, fuelAmount, fuelType, isJerryCan)
- pricePaid = math.floor(pricePaid)
-
- if not isFuelTypeValid(fuelType) then
- print("Invalid fuel type: "..(fuelType or "nil"))
- return false
- end
-
- -- If not owned
- local stationData = getStationDataFromConfig()
- if not gasStationId then
- if stationData.stationStock[fuelType] >= fuelAmount then
- -- If set in config to unowed gas stations have stock
- return true
- else
- return false
- end
- end
-
- local column = "stock_"..fuelType
- if fuelType == "regular" then
- column = "stock"
- end
-
- local sql = "SELECT "..column.." as stock FROM gas_station_business WHERE gas_station_id = @gas_station_id";
- local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
-
- if not query then
- if stationData.stationStock[fuelType] >= fuelAmount then
- -- If set in config to unowed gas stations have stock
- return true
- else
- return false
- end
- end
-
- if isFuelTypeElectric(fuelType) then
- if query.stock < 1 then
- return false
- end
-
- local sql = "UPDATE `gas_station_business` SET customers = customers + 1, money = money + @price, total_money_earned = total_money_earned + @price WHERE gas_station_id = @gas_station_id";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@price'] = pricePaid, ['@amount'] = fuelAmount});
-
- if isJerryCan then
- print("Jerry can in electric charger???")
- return false
- else
- local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_electric'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
- end
- else
- if query.stock < fuelAmount then
- return false
- end
-
- local sql = "UPDATE `gas_station_business` SET "..column.." = @stock, customers = customers + 1, money = money + @price, total_money_earned = total_money_earned + @price, gas_sold = gas_sold + @amount WHERE gas_station_id = @gas_station_id";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@stock'] = (query.stock - fuelAmount), ['@price'] = pricePaid, ['@amount'] = fuelAmount});
-
- if isJerryCan then
- local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_jerry_can'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
- else
- local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
- Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_fuel'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
- end
- end
- return true
-end
-
-function returnStockToGasStation(gasStationId, priceRefunded, fuelAmount, fuelType)
- priceRefunded = math.floor(priceRefunded)
-
- if not isFuelTypeValid(fuelType) then
- print("Invalid fuel type: "..(fuelType or "nil"))
- return false, 0
- end
-
- -- If not owned
- local stationData = getStationDataFromConfig()
- if not gasStationId then
- if stationData.stationStock[fuelType] >= fuelAmount then
- -- If set in config to unowed gas stations have stock
- return true, priceRefunded
- else
- return false, 0
- end
- end
-
- local column = "stock_"..fuelType
- if fuelType == "regular" then
- column = "stock"
- end
-
- local sql = "SELECT "..column.." as stock, money, total_money_earned, gas_sold FROM gas_station_business WHERE gas_station_id = @gas_station_id";
- local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
-
- if not query then
- if stationData.stationStock[fuelType] >= fuelAmount then
- -- If set in config to unowed gas stations have stock
- return true, priceRefunded
- else
- return false, 0
- end
- end
-
- local actualRefund = 0
-
- if isFuelTypeElectric(fuelType) then
- actualRefund = math.min(priceRefunded, query.money)
-
- local newMoney = math.max(query.money - actualRefund, 0)
- local newTotalEarned = math.max(query.total_money_earned - actualRefund, 0)
-
- local sql = "UPDATE `gas_station_business` SET money = @money, total_money_earned = @total WHERE gas_station_id = @gas_station_id";
- Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@money'] = newMoney, ['@total'] = newTotalEarned })
-
- local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
- Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@income'] = 1, ['@title'] = Utils.translate('owned_gas_stations.refund_electric'):format(fuelAmount), ['@amount'] = actualRefund, ['@date'] = os.time() })
- else
- actualRefund = math.min(priceRefunded, query.money)
-
- local newStock = query.stock + fuelAmount
- local newMoney = math.max(query.money - actualRefund, 0)
- local newTotalEarned = math.max(query.total_money_earned - actualRefund, 0)
- local newGasSold = math.max((query.gas_sold or 0) - fuelAmount, 0)
-
- local sql = "UPDATE `gas_station_business` SET "..column.." = @stock, money = @money, total_money_earned = @total, gas_sold = @sold WHERE gas_station_id = @gas_station_id";
- Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@stock'] = newStock, ['@money'] = newMoney, ['@total'] = newTotalEarned, ['@sold'] = newGasSold })
-
- local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
- Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@income'] = 1, ['@title'] = Utils.translate('owned_gas_stations.refund_fuel'):format(fuelAmount), ['@amount'] = actualRefund, ['@date'] = os.time() })
- end
- return true, actualRefund
-end
-
------------------------------------------------------------------------------------------------------------------------------------------
--- Utils functions
------------------------------------------------------------------------------------------------------------------------------------------
-
-function getStationDataFromConfig()
- return {
- pricePerLiter = {
- regular = Config.DefaultValues.fuelPrice.regular,
- plus = Config.DefaultValues.fuelPrice.plus,
- premium = Config.DefaultValues.fuelPrice.premium,
- diesel = Config.DefaultValues.fuelPrice.diesel,
- electricfast = Config.Electric.chargeTypes.fast.price,
- electricnormal = Config.Electric.chargeTypes.normal.price,
- },
- stationStock = {
- regular = Config.DefaultValues.fuelStock.regular and 1000 or 0,
- plus = Config.DefaultValues.fuelStock.plus and 1000 or 0,
- premium = Config.DefaultValues.fuelStock.premium and 1000 or 0,
- diesel = Config.DefaultValues.fuelStock.diesel and 1000 or 0,
- electricfast = Config.Electric.chargeTypes.fast.stock and 1000 or 0,
- electricnormal = Config.Electric.chargeTypes.normal.stock and 1000 or 0,
- }
- }
-end
-
-function isFuelTypeValid(fuelType)
- return Utils.Table.contains({"regular", "plus", "premium", "diesel", "electricfast", "electricnormal"}, fuelType)
-end
-
-function isFuelTypeElectric(fuelType)
- return Utils.Table.contains({"electricnormal", "electricfast"}, fuelType)
-end
-
-function isPaymentMethodValid(paymentMethod)
- return Utils.Table.contains({"account1", "account2"}, paymentMethod) -- These are not really the account, but the index to the Config.Accounts
-end
-
-function getPlayerDiscountAmount(source)
- local job, onDuty = Utils.Framework.getPlayerJob(source)
- if onDuty and job and Config.JobDiscounts[job] then
- return Config.JobDiscounts[job]
- end
- return 0
-end
-
-Utils.Callback.RegisterServerCallback('lc_fuel:getVehicleFuelType', function(source, cb, plate)
- cb(getVehicleFuelType(plate))
-end)
-
-RegisterServerEvent("lc_fuel:setVehicleFuelType")
-AddEventHandler("lc_fuel:setVehicleFuelType",function(plate, fuelType)
- setVehicleFuelType(plate, fuelType)
-end)
-
-function getVehicleFuelType(plate)
- return playerVehiclesFuelType[plate] or "default"
-end
-
-function setVehicleFuelType(plate, fuelType)
- if not isFuelTypeValid(fuelType) then
- fuelType = "regular"
- print("Invalid fuel type ("..fuelType..") set to vehicle ("..plate..")")
- end
-
- playerVehiclesFuelType[plate] = fuelType
- local sql = [[
- INSERT INTO `player_vehicles_fuel_type` (plate, fuelType)
- VALUES (@plate, @fuelType)
- ON DUPLICATE KEY UPDATE fuelType = @fuelType
- ]];
- Utils.Database.execute(sql, {['@plate'] = plate, ['@fuelType'] = fuelType})
-end
-
-function cacheplayerVehiclesFuelTypeType()
- local sql = "SELECT * FROM player_vehicles_fuel_type";
- local queryData = Utils.Database.fetchAll(sql, {});
- for _, value in pairs(queryData) do
- playerVehiclesFuelType[value.plate] = value.fuelType
- end
- print("^2[lc_fuel] Fuel types successfully fetched from database^7")
-end
-
-function Wrapper(source,cb)
- if utils_outdated then
- TriggerClientEvent("lc_fuel:Notify",source,"error","The script requires 'lc_utils' in version "..utils_required_version..", but you currently have version "..Utils.Version..". Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip")
- return
- end
-
- if cooldown[source] == nil then
- cooldown[source] = true
- local user_id = Utils.Framework.getPlayerId(source)
- if user_id then
- cb(user_id)
- else
- print("User not found: "..source)
- end
- SetTimeout(100,function()
- cooldown[source] = nil
- end)
- end
-end
-
-
-Citizen.CreateThread(function()
- Wait(1000)
-
- -- Load version number from file
- local versionFile = LoadResourceFile("lc_fuel", "version")
- if versionFile then
- version = Utils.Math.trim(versionFile)
- print("^2[lc_fuel] Loaded! Support discord: https://discord.gg/U5YDgbh ^3[v"..version..subversion.."]^7")
- else
- error("^1[lc_fuel] Warning: Could not load the version file.^7")
- end
-
- checkIfFrameworkWasLoaded()
- checkScriptName()
-
- -- Startup queries
- runCreateTableQueries()
- cacheplayerVehiclesFuelTypeType()
-
- -- Config checker
- assert(Config.FuelConsumptionPerClass, "^3You have errors in your config file, consider fixing it or redownload the original config.^7")
-
- -- Check lc_utils dependency
- assert(GetResourceState('lc_utils') == 'started', "^3The '^1lc_utils^3' file is missing. Please refer to the documentation for installation instructions: ^7https://docs.lixeirocharmoso.com/fuel/installation^7")
-
- if Utils.Math.checkIfCurrentVersionisOutdated(utils_required_version, Utils.Version) then
- utils_outdated = true
- error("^3The script requires 'lc_utils' in version ^1"..utils_required_version.."^3, but you currently have version ^1"..Utils.Version.."^3. Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip^7")
- end
-
- -- Load langs
- Utils.loadLanguageFile(Lang)
-
- -- Config validator
- local configs_to_validate = {
- { config_path = {"Blips", "onlyShowNearestBlip"}, default_value = false },
- { config_path = {"ReturnNozzleRefund"}, default_value = true },
- }
- Config = Utils.validateConfig(Config, configs_to_validate)
-
- Wait(1000)
-
- checkVersion()
-end)
-
-function checkIfFrameworkWasLoaded()
- assert(Utils.Framework.getPlayerId, "^3The framework wasn't loaded in the '^1lc_utils^3' resource. Please check if the '^1Config.framework^3' is correctly set to your framework, and make sure there are no errors in your file. For more information, refer to the documentation at '^7https://docs.lixeirocharmoso.com/^3'.^7")
-end
-
-function checkScriptName()
- assert(GetCurrentResourceName() == "lc_fuel", "^3The script name does not match the expected resource name. Please ensure that the current resource name is set to '^1lc_fuel^7'.")
-end
-
-function runCreateTableQueries()
- Utils.Database.execute([[
- CREATE TABLE IF NOT EXISTS `player_vehicles_fuel_type` (
- `plate` VARCHAR(20) NOT NULL COLLATE 'utf8_general_ci',
- `fuelType` VARCHAR(20) NOT NULL COLLATE 'utf8_general_ci',
- PRIMARY KEY (`plate`) USING BTREE
- )
- COLLATE='utf8_general_ci'
- ENGINE=InnoDB
- ;
- ]])
-end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Versioning
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+version = ''
+subversion = ''
+api_response = {}
+local utils_required_version = '1.2.1'
+local utils_outdated = false
+
+function checkVersion()
+ CreateThread(function()
+ local connected = false
+ local attempts = 0
+ while not connected and attempts < 3 do
+ attempts = attempts + 1
+
+ PerformHttpRequest("https://raw.githubusercontent.com/LeonardoSoares98/lc_fuel/main/version", function(errorCode, resultData)
+ if errorCode == 200 and resultData then
+ connected = true
+ local latest_version = Utils.Math.trim(resultData)
+
+ api_response.latest_version = latest_version
+ if Utils.Math.checkIfCurrentVersionisOutdated(latest_version, version) then
+ api_response.has_update = true
+ print("^4["..GetCurrentResourceName().."] An update is available, download it in https://github.com/LeonardoSoares98/lc_fuel/releases/latest/download/lc_fuel.zip^7 ^3[v"..api_response.latest_version.."]^7")
+ else
+ api_response.has_update = false
+ end
+ end
+ end, "GET", "", {})
+
+ Wait(10000)
+ end
+ end)
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Script global variables
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+Utils = Utils or exports['lc_utils']:GetUtils()
+local cooldown = {}
+local playerVehiclesFuelType = {}
+local fuelPurchased = {}
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Script functions
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+RegisterServerEvent("lc_fuel:serverOpenUI")
+AddEventHandler("lc_fuel:serverOpenUI",function(isElectric, pumpModel, vehicleFuel, vehicleTankSize, vehiclePlate)
+ local source = source
+ Wrapper(source,function(user_id)
+ local gasStationId = getCurrentGasStationId(source)
+ serverOpenUI(source, isElectric, pumpModel, gasStationId, vehicleFuel, vehicleTankSize, vehiclePlate)
+ end)
+end)
+
+RegisterServerEvent("lc_fuel:confirmRefuel")
+AddEventHandler("lc_fuel:confirmRefuel",function(data)
+ local source = source
+ Wrapper(source,function(user_id)
+ if not data or data.fuelAmount <= 0 or not isFuelTypeValid(data.selectedFuelType) or not isPaymentMethodValid(data.paymentMethod) then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('invalid_value'))
+ return
+ end
+
+ local gasStationId = getCurrentGasStationId(source)
+ local stationData = getStationData(gasStationId)
+ local pricePerLiter = stationData.pricePerLiter[data.selectedFuelType]
+ local initialPrice = pricePerLiter * data.fuelAmount
+
+ local discount = getPlayerDiscountAmount(source)
+ local finalPrice = initialPrice * (1 - (discount / 100))
+ if Utils.Framework.getPlayerAccountMoney(source, Config.Accounts[data.paymentMethod]) < finalPrice then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_money'):format(Utils.numberFormat(finalPrice)))
+ return
+ end
+
+ if not removeStockFromStation(gasStationId, finalPrice, data.fuelAmount, data.selectedFuelType, false) then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
+ return
+ end
+
+ Utils.Framework.tryRemoveAccountMoney(source, finalPrice, Config.Accounts[data.paymentMethod])
+
+ fuelPurchased[source] = {
+ finalPrice = finalPrice,
+ account = Config.Accounts[data.paymentMethod],
+ selectedFuelType = data.selectedFuelType,
+ fuelAmount = data.fuelAmount,
+ pricePerLiter = pricePerLiter,
+ }
+
+ TriggerClientEvent("lc_fuel:getPumpNozzle", source, data.fuelAmount, data.selectedFuelType)
+ TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('refuel_paid'):format(Utils.numberFormat(finalPrice)))
+ end)
+end)
+
+
+RegisterServerEvent("lc_fuel:returnNozzle")
+AddEventHandler("lc_fuel:returnNozzle",function(remainingFuel, isElectric)
+ local source = source
+ Wrapper(source,function(user_id)
+
+ if not Config.ReturnNozzleRefund then
+ return
+ end
+
+ if not fuelPurchased[source] then
+ return
+ end
+
+ if remainingFuel < 1 then
+ fuelPurchased[source] = nil
+ return
+ end
+
+ local discount = getPlayerDiscountAmount(source)
+ local amountToReturn = math.floor(remainingFuel * (fuelPurchased[source].pricePerLiter * (1 - (discount / 100))))
+
+ if amountToReturn > fuelPurchased[source].finalPrice or remainingFuel > fuelPurchased[source].fuelAmount then
+ print("User "..user_id.." initially purchased "..fuelPurchased[source].fuelAmount.."L of fuel but now is returning "..remainingFuel.."L. Is this user trying to glitch something?")
+ print("User coords: "..GetEntityCoords(GetPlayerPed(source)))
+ fuelPurchased[source] = nil
+ return
+ end
+
+ local gasStationId = getCurrentGasStationId(source)
+ local _, returnedAmount = returnStockToGasStation(gasStationId, amountToReturn, remainingFuel, fuelPurchased[source].selectedFuelType)
+
+ if isElectric then
+ TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('returned_charge'):format(Utils.Math.round(remainingFuel, 1), returnedAmount))
+ else
+ TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('returned_fuel'):format(Utils.Math.round(remainingFuel, 1), returnedAmount))
+ end
+ Utils.Framework.giveAccountMoney(source, returnedAmount, fuelPurchased[source].account)
+
+ fuelPurchased[source] = nil
+ end)
+end)
+
+RegisterServerEvent("lc_fuel:confirmJerryCanPurchase")
+AddEventHandler("lc_fuel:confirmJerryCanPurchase",function(data)
+ if not Config.JerryCan.enabled then return end
+ local source = source
+ Wrapper(source,function(user_id)
+ if not isPaymentMethodValid(data.paymentMethod) then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('invalid_value'))
+ return
+ end
+
+ local gasStationId = getCurrentGasStationId(source)
+ local stationData = getStationData(gasStationId)
+ local fuelType = nil
+ -- Check which type has enough stock
+ if stationData.stationStock.regular >= Config.JerryCan.requiredStock then
+ fuelType = "regular"
+ elseif stationData.stationStock.plus >= Config.JerryCan.requiredStock then
+ fuelType = "plus"
+ elseif stationData.stationStock.premium >= Config.JerryCan.requiredStock then
+ fuelType = "premium"
+ elseif stationData.stationStock.diesel >= Config.JerryCan.requiredStock then
+ fuelType = "diesel"
+ end
+
+ if fuelType == nil then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
+ return
+ end
+
+ if Utils.Framework.getPlayerAccountMoney(source, Config.Accounts[data.paymentMethod]) < Config.JerryCan.price then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_money'):format(Config.JerryCan.price))
+ return
+ end
+
+ if not removeStockFromStation(gasStationId, Config.JerryCan.price, Config.JerryCan.requiredStock, fuelType, true) then
+ TriggerClientEvent("lc_fuel:Notify", source, "error", Utils.translate('not_enough_stock'))
+ return
+ end
+ Utils.Framework.tryRemoveAccountMoney(source, Config.JerryCan.price, Config.Accounts[data.paymentMethod])
+
+ -- Gives the jerry can to the player
+ if Config.JerryCan.giveAsWeapon then
+ Utils.Framework.givePlayerWeapon(source, Config.JerryCan.item, 1, Config.JerryCan.metadata)
+ else
+ Utils.Framework.givePlayerItem(source, Config.JerryCan.item, 1, Config.JerryCan.metadata)
+ end
+
+ TriggerClientEvent("lc_fuel:Notify", source, "success", Utils.translate('jerry_can_paid'):format(Config.JerryCan.price))
+ TriggerClientEvent("lc_fuel:closeUI", source, data.fuelAmount, data.selectedFuelType)
+ end)
+end)
+
+function serverOpenUI(source, isElectric, pumpModel, gasStationId, vehicleFuel, vehicleTankSize, vehiclePlate)
+ local stationData = getStationData(gasStationId)
+ local discount = getPlayerDiscountAmount(source)
+
+ local data = {
+ pricePerLiter = stationData.pricePerLiter,
+ stationStock = stationData.stationStock,
+ currentFuelType = getVehicleFuelType(vehiclePlate),
+ vehicleFuel = vehicleFuel or 0,
+ vehicleTankSize = vehicleTankSize or 100,
+ cashBalance = Utils.Framework.getPlayerAccountMoney(source, Config.Accounts.account1),
+ bankBalance = Utils.Framework.getPlayerAccountMoney(source, Config.Accounts.account2),
+ jerryCan = Config.JerryCan,
+ isElectric = isElectric,
+ electric = Config.Electric,
+ pumpModel = pumpModel,
+ }
+
+ -- Apply the discount to each fuel type price based on player job
+ for fuelType, price in pairs(stationData.pricePerLiter) do
+ data.pricePerLiter[fuelType] = price * (1 - (discount / 100))
+ end
+
+ TriggerClientEvent("lc_fuel:clientOpenUI", source, data)
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Gas Station stock functions
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function getCurrentGasStationId(source)
+ if not Config.PlayerOwnedGasStations.enabled then return nil end
+ local playerCoords = GetEntityCoords(GetPlayerPed(source))
+ for k,v in pairs(Config.PlayerOwnedGasStations.gasStations) do
+ if #(v.vector - playerCoords) <= v.radius then
+ return k
+ end
+ end
+ return nil
+end
+
+function getStationData(gasStationId)
+ local stationData = getStationDataFromConfig()
+ if not gasStationId then
+ return stationData
+ end
+
+ local sql = "SELECT price, stock, price_plus, stock_plus, price_premium, stock_premium, price_diesel, stock_diesel, price_electricfast, stock_electricfast, price_electricnormal, stock_electricnormal FROM gas_station_business WHERE gas_station_id = @gas_station_id";
+ local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
+
+ if not query then
+ return stationData
+ end
+
+ local sql = "UPDATE `gas_station_business` SET total_visits = total_visits + 1 WHERE gas_station_id = @gas_station_id";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId});
+
+ stationData = {
+ pricePerLiter = {
+ regular = query.price/100,
+ plus = query.price_plus/100,
+ premium = query.price_premium/100,
+ diesel = query.price_diesel/100,
+ electricfast = query.price_electricfast/100,
+ electricnormal = query.price_electricnormal/100,
+ },
+ stationStock = {
+ regular = query.stock,
+ plus = query.stock_plus,
+ premium = query.stock_premium,
+ diesel = query.stock_diesel,
+ electricfast = query.stock_electricfast == 1 and 100 or 0,
+ electricnormal = query.stock_electricnormal == 1 and 100 or 0,
+ }
+ }
+
+ return stationData
+end
+
+function removeStockFromStation(gasStationId, pricePaid, fuelAmount, fuelType, isJerryCan)
+ pricePaid = math.floor(pricePaid)
+
+ if not isFuelTypeValid(fuelType) then
+ print("Invalid fuel type: "..(fuelType or "nil"))
+ return false
+ end
+
+ -- If not owned
+ local stationData = getStationDataFromConfig()
+ if not gasStationId then
+ if stationData.stationStock[fuelType] >= fuelAmount then
+ -- If set in config to unowed gas stations have stock
+ return true
+ else
+ return false
+ end
+ end
+
+ local column = "stock_"..fuelType
+ if fuelType == "regular" then
+ column = "stock"
+ end
+
+ local sql = "SELECT "..column.." as stock FROM gas_station_business WHERE gas_station_id = @gas_station_id";
+ local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
+
+ if not query then
+ if stationData.stationStock[fuelType] >= fuelAmount then
+ -- If set in config to unowed gas stations have stock
+ return true
+ else
+ return false
+ end
+ end
+
+ if isFuelTypeElectric(fuelType) then
+ if query.stock < 1 then
+ return false
+ end
+
+ local sql = "UPDATE `gas_station_business` SET customers = customers + 1, money = money + @price, total_money_earned = total_money_earned + @price WHERE gas_station_id = @gas_station_id";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@price'] = pricePaid, ['@amount'] = fuelAmount});
+
+ if isJerryCan then
+ print("Jerry can in electric charger???")
+ return false
+ else
+ local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_electric'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
+ end
+ else
+ if query.stock < fuelAmount then
+ return false
+ end
+
+ local sql = "UPDATE `gas_station_business` SET "..column.." = @stock, customers = customers + 1, money = money + @price, total_money_earned = total_money_earned + @price, gas_sold = gas_sold + @amount WHERE gas_station_id = @gas_station_id";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@stock'] = (query.stock - fuelAmount), ['@price'] = pricePaid, ['@amount'] = fuelAmount});
+
+ if isJerryCan then
+ local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_jerry_can'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
+ else
+ local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
+ Utils.Database.execute(sql, {['@gas_station_id'] = gasStationId, ['@income'] = 0, ['@title'] = Utils.translate('owned_gas_stations.balance_fuel'):format(fuelAmount), ['@amount'] = pricePaid, ['@date'] = os.time()});
+ end
+ end
+ return true
+end
+
+function returnStockToGasStation(gasStationId, priceRefunded, fuelAmount, fuelType)
+ priceRefunded = math.floor(priceRefunded)
+
+ if not isFuelTypeValid(fuelType) then
+ print("Invalid fuel type: "..(fuelType or "nil"))
+ return false, 0
+ end
+
+ -- If not owned
+ local stationData = getStationDataFromConfig()
+ if not gasStationId then
+ if stationData.stationStock[fuelType] >= fuelAmount then
+ -- If set in config to unowed gas stations have stock
+ return true, priceRefunded
+ else
+ return false, 0
+ end
+ end
+
+ local column = "stock_"..fuelType
+ if fuelType == "regular" then
+ column = "stock"
+ end
+
+ local sql = "SELECT "..column.." as stock, money, total_money_earned, gas_sold FROM gas_station_business WHERE gas_station_id = @gas_station_id";
+ local query = Utils.Database.fetchAll(sql, {['@gas_station_id'] = gasStationId})[1];
+
+ if not query then
+ if stationData.stationStock[fuelType] >= fuelAmount then
+ -- If set in config to unowed gas stations have stock
+ return true, priceRefunded
+ else
+ return false, 0
+ end
+ end
+
+ local actualRefund = 0
+
+ if isFuelTypeElectric(fuelType) then
+ actualRefund = math.min(priceRefunded, query.money)
+
+ local newMoney = math.max(query.money - actualRefund, 0)
+ local newTotalEarned = math.max(query.total_money_earned - actualRefund, 0)
+
+ local sql = "UPDATE `gas_station_business` SET money = @money, total_money_earned = @total WHERE gas_station_id = @gas_station_id";
+ Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@money'] = newMoney, ['@total'] = newTotalEarned })
+
+ local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
+ Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@income'] = 1, ['@title'] = Utils.translate('owned_gas_stations.refund_electric'):format(fuelAmount), ['@amount'] = actualRefund, ['@date'] = os.time() })
+ else
+ actualRefund = math.min(priceRefunded, query.money)
+
+ local newStock = query.stock + fuelAmount
+ local newMoney = math.max(query.money - actualRefund, 0)
+ local newTotalEarned = math.max(query.total_money_earned - actualRefund, 0)
+ local newGasSold = math.max((query.gas_sold or 0) - fuelAmount, 0)
+
+ local sql = "UPDATE `gas_station_business` SET "..column.." = @stock, money = @money, total_money_earned = @total, gas_sold = @sold WHERE gas_station_id = @gas_station_id";
+ Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@stock'] = newStock, ['@money'] = newMoney, ['@total'] = newTotalEarned, ['@sold'] = newGasSold })
+
+ local sql = "INSERT INTO `gas_station_balance` (gas_station_id,income,title,amount,date) VALUES (@gas_station_id,@income,@title,@amount,@date)";
+ Utils.Database.execute(sql, { ['@gas_station_id'] = gasStationId, ['@income'] = 1, ['@title'] = Utils.translate('owned_gas_stations.refund_fuel'):format(fuelAmount), ['@amount'] = actualRefund, ['@date'] = os.time() })
+ end
+ return true, actualRefund
+end
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+-- Utils functions
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+function getStationDataFromConfig()
+ return {
+ pricePerLiter = {
+ regular = Config.DefaultValues.fuelPrice.regular,
+ plus = Config.DefaultValues.fuelPrice.plus,
+ premium = Config.DefaultValues.fuelPrice.premium,
+ diesel = Config.DefaultValues.fuelPrice.diesel,
+ electricfast = Config.Electric.chargeTypes.fast.price,
+ electricnormal = Config.Electric.chargeTypes.normal.price,
+ },
+ stationStock = {
+ regular = Config.DefaultValues.fuelStock.regular and 1000 or 0,
+ plus = Config.DefaultValues.fuelStock.plus and 1000 or 0,
+ premium = Config.DefaultValues.fuelStock.premium and 1000 or 0,
+ diesel = Config.DefaultValues.fuelStock.diesel and 1000 or 0,
+ electricfast = Config.Electric.chargeTypes.fast.stock and 1000 or 0,
+ electricnormal = Config.Electric.chargeTypes.normal.stock and 1000 or 0,
+ }
+ }
+end
+
+function isFuelTypeValid(fuelType)
+ return Utils.Table.contains({"regular", "plus", "premium", "diesel", "electricfast", "electricnormal"}, fuelType)
+end
+
+function isFuelTypeElectric(fuelType)
+ return Utils.Table.contains({"electricnormal", "electricfast"}, fuelType)
+end
+
+function isPaymentMethodValid(paymentMethod)
+ return Utils.Table.contains({"account1", "account2"}, paymentMethod) -- These are not really the account, but the index to the Config.Accounts
+end
+
+function getPlayerDiscountAmount(source)
+ local job, onDuty = Utils.Framework.getPlayerJob(source)
+ if onDuty and job and Config.JobDiscounts[job] then
+ return Config.JobDiscounts[job]
+ end
+ return 0
+end
+
+Utils.Callback.RegisterServerCallback('lc_fuel:getVehicleFuelType', function(source, cb, plate)
+ cb(getVehicleFuelType(plate))
+end)
+
+RegisterServerEvent("lc_fuel:setVehicleFuelType")
+AddEventHandler("lc_fuel:setVehicleFuelType",function(plate, fuelType)
+ setVehicleFuelType(plate, fuelType)
+end)
+
+function getVehicleFuelType(plate)
+ return playerVehiclesFuelType[plate] or "default"
+end
+
+function setVehicleFuelType(plate, fuelType)
+ if not isFuelTypeValid(fuelType) then
+ print("Invalid fuel type ("..fuelType..") set to vehicle ("..plate..")")
+ fuelType = "regular"
+ end
+
+ playerVehiclesFuelType[plate] = fuelType
+ -- Only store in database if the vehicle is in player vehicles table
+ if Config.SaveAllVehicleFuelTypes == true or (Utils.Framework.getVehicleOwner(Utils.Math.trim(plate)) ~= false or Utils.Framework.getVehicleOwner(plate) ~= false) then
+ local sql = [[
+ INSERT INTO `player_vehicles_fuel_type` (plate, fuelType)
+ VALUES (@plate, @fuelType)
+ ON DUPLICATE KEY UPDATE fuelType = @fuelType
+ ]];
+ Utils.Database.execute(sql, {['@plate'] = plate, ['@fuelType'] = fuelType})
+ end
+end
+
+function cacheplayerVehiclesFuelTypeType()
+ local sql = "SELECT * FROM player_vehicles_fuel_type";
+ local queryData = Utils.Database.fetchAll(sql, {});
+ for _, value in pairs(queryData) do
+ playerVehiclesFuelType[value.plate] = value.fuelType
+ end
+ print("^2[lc_fuel] #"..#queryData.." Fuel types successfully fetched from database^7")
+end
+
+function Wrapper(source,cb)
+ if utils_outdated then
+ TriggerClientEvent("lc_fuel:Notify",source,"error","The script requires 'lc_utils' in version "..utils_required_version..", but you currently have version "..Utils.Version..". Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip")
+ return
+ end
+
+ if cooldown[source] == nil then
+ cooldown[source] = true
+ local user_id = Utils.Framework.getPlayerId(source)
+ if user_id then
+ cb(user_id)
+ else
+ print("User not found: "..source)
+ end
+ SetTimeout(100,function()
+ cooldown[source] = nil
+ end)
+ end
+end
+
+
+Citizen.CreateThread(function()
+ Wait(1000)
+
+ -- Load version number from file
+ local versionFile = LoadResourceFile("lc_fuel", "version")
+ if versionFile then
+ version = Utils.Math.trim(versionFile)
+ print("^2[lc_fuel] Loaded! Support discord: https://discord.gg/U5YDgbh ^3[v"..version..subversion.."]^7")
+ else
+ error("^1[lc_fuel] Warning: Could not load the version file.^7")
+ end
+
+ checkIfFrameworkWasLoaded()
+ checkScriptName()
+
+ -- Startup queries
+ runCreateTableQueries()
+ cacheplayerVehiclesFuelTypeType()
+
+ -- Config checker
+ assert(Config.FuelConsumptionPerClass, "^3You have errors in your config file, consider fixing it or redownload the original config.^7")
+
+ -- Check lc_utils dependency
+ assert(GetResourceState('lc_utils') == 'started', "^3The '^1lc_utils^3' file is missing. Please refer to the documentation for installation instructions: ^7https://docs.lixeirocharmoso.com/fuel/installation^7")
+
+ if Utils.Math.checkIfCurrentVersionisOutdated(utils_required_version, Utils.Version) then
+ utils_outdated = true
+ error("^3The script requires 'lc_utils' in version ^1"..utils_required_version.."^3, but you currently have version ^1"..Utils.Version.."^3. Please update your 'lc_utils' script to the latest version: https://github.com/LeonardoSoares98/lc_utils/releases/latest/download/lc_utils.zip^7")
+ end
+
+ -- Load langs
+ Utils.loadLanguageFile(Lang)
+
+ -- Config validator
+ local configs_to_validate = {
+ { config_path = {"Blips", "onlyShowNearestBlip"}, default_value = false },
+ { config_path = {"ReturnNozzleRefund"}, default_value = true },
+ }
+ Config = Utils.validateConfig(Config, configs_to_validate)
+
+ Wait(1000)
+
+ checkVersion()
+end)
+
+function checkIfFrameworkWasLoaded()
+ assert(Utils.Framework.getPlayerId, "^3The framework wasn't loaded in the '^1lc_utils^3' resource. Please check if the '^1Config.framework^3' is correctly set to your framework, and make sure there are no errors in your file. For more information, refer to the documentation at '^7https://docs.lixeirocharmoso.com/^3'.^7")
+end
+
+function checkScriptName()
+ assert(GetCurrentResourceName() == "lc_fuel", "^3The script name does not match the expected resource name. Please ensure that the current resource name is set to '^1lc_fuel^7'.")
+end
+
+function runCreateTableQueries()
+ Utils.Database.execute([[
+ CREATE TABLE IF NOT EXISTS `player_vehicles_fuel_type` (
+ `plate` VARCHAR(20) NOT NULL COLLATE 'utf8_general_ci',
+ `fuelType` VARCHAR(20) NOT NULL COLLATE 'utf8_general_ci',
+ PRIMARY KEY (`plate`) USING BTREE
+ )
+ COLLATE='utf8_general_ci'
+ ENGINE=InnoDB
+ ;
+ ]])
+end
diff --git a/resources/[carscripts]/lc_fuel/version b/resources/[carscripts]/lc_fuel/version
index d2d61a7e8..e2cac26c1 100644
--- a/resources/[carscripts]/lc_fuel/version
+++ b/resources/[carscripts]/lc_fuel/version
@@ -1 +1 @@
-1.2.2
\ No newline at end of file
+1.2.3
\ No newline at end of file