Full View config.lua

Preview File Updated: v1.1.2 - 03.01.2025

Config = {}

-- █▀ █▀▄ ▄▀▄ █▄ ▄█ ██▀ █   █ ▄▀▄ █▀▄ █▄▀
-- █▀ █▀▄ █▀█ █ ▀ █ █▄▄ ▀▄▀▄▀ ▀▄▀ █▀▄ █ █
local frameworkAutoFind = function()
    if GetResourceState('es_extended') == 'started' then
        return "ESX"
    elseif GetResourceState('qb-core') == 'started' then
        return "QB-Core"
    end
end

Config.Core = frameworkAutoFind()
Config.CoreExport = function()
    if Config.Core == "ESX" then
        return exports['es_extended']:getSharedObject()
    elseif Config.Core == "QB-Core" then
        return exports['qb-core']:GetCoreObject()
    end
end

---@field PlayerLoaded string: ESX: "esx:playerLoaded" / QB-Core: "QBCore:Client:OnPlayerLoaded"
Config.PlayerLoaded = Config.Core == "ESX" and "esx:playerLoaded" or "QBCore:Client:OnPlayerLoaded"

---@field PlayerDropped string: ESX: "esx:playerDropped" / QB-Core: "playerDropped"
Config.PlayerDropped = Config.Core == "ESX" and "esx:playerDropped" or "playerDropped"


Config.Notification = function(message, type)
    if type == "success" then
        if GetResourceState("vms_notify") == 'started' then
            exports['vms_notify']:Notification("DRIVE SCHOOL", message, 5000, "#32a852", "fa-solid fa-graduation-cap")
        else
            TriggerEvent('esx:showNotification', message)
            TriggerEvent('QBCore:Notify', message, 'success', 5000)
        end
    elseif type == "error" then
        if GetResourceState("vms_notify") == 'started' then
            exports['vms_notify']:Notification("DRIVE SCHOOL", message, 5000, "#eb4034", "fa-solid fa-graduation-cap")
        else
            TriggerEvent('esx:showNotification', message)
            TriggerEvent('QBCore:Notify', message, 'error', 5000)
        end
    end
end

Config.Interact = {
    Enabled = false,
    Open = function(message)
        exports["interact"]:Open("E", message) -- Here you can use your TextUI or use my free one - https://github.com/vames-dev/interact
        -- exports['qb-core']:DrawText(message, 'right')
    end,
    Close = function()
        exports["interact"]:Close() -- Here you can use your TextUI or use my free one - https://github.com/vames-dev/interact
        -- exports['qb-core']:HideText()
    end,
}


-- █▄ ▄█ ▄▀▄ █ █▄ █   ▄▀▀ ██▀ ▀█▀ ▀█▀ █ █▄ █ ▄▀  ▄▀▀
-- █ ▀ █ █▀█ █ █ ▀█   ▄██ █▄▄  █   █  █ █ ▀█ ▀▄█ ▄██
---@field AccessOnMarker boolean: Do you want to use access to the exam selection menu as E in marker?
Config.AccessOnMarker = true
Config.UseTarget = false
Config.TargetResource = 'ox_target'
Config.Target = function()
    exports[Config.TargetResource]:addBoxZone({
        coords = vec(Config.Zones["menu"].coords.x, Config.Zones["menu"].coords.y, Config.Zones["menu"].coords.z+0.35),
        size = vec(4.0, 4.0, 4.0),
        debug = false,
        useZ = true,
        rotation = 60,
        distance = 9.0,
        options = {
            {
                name = 'driveschoolv2',
                event = 'vms_driveschoolv2:openMenu',
                icon = 'fa-regular fa-file-lines',
                label = "Drive School"
            }
        }
    })
end

---@field UseVMSCityHall boolean: 
Config.UseVMSCityHall = GetResourceState('vms_cithall') == 'started'

---@field UseSoundsUI boolean: Do you want to use interaction sounds in the UI?
Config.UseSoundsUI = true

---@field EnableBlur boolean: Do you want to blur the background in the game when you have the UI running?
Config.EnableBlur = true 

---@field PossibleChargeByBank boolean: if you set it true, when the player does not have enough cash, it will try to take it from his bank account
Config.PossibleChargeByBank = true

---@field MaxSpeedLoopTimeout number: if Config.EnableMaxSpeedLoop = true and exceeds the maximum speed, will have 1 second (1000 milliseconds) to reduce the speed, otherwise another error will be charged
Config.MaxSpeedLoopTimeout = 1000
Config.EnableMaxSpeedLoop = true

---@field MaxSpeed number or nil: maximum speed / if you dont want a speed limit set nil
Config.MaxSpeed = 50
Config.SpeedMultiplier = 3.6 -- kmh = 3.6 / mph = 2.236936

---@field MaxDriveErrors number: How much maximum a player can get bugs for vehicle damage, on 5 will require going back to driving school and failing the test
Config.MaxDriveErrors = 5

---@field CheckIsManeuveringAreaIsOccupied boolean: If the maneuvering area is occupied, the practical exam will not start and the player will receive notification about it
Config.CheckIsManeuveringAreaIsOccupied = true
Config.ManeuveringAreaCoords = {
    {coords = vector3(-720.33, -2212.69, 5.0), radius = 5.0},
    {coords = vector3(-725.85, -2208.24, 5.0), radius = 7.0},
    {coords = vector3(-733.66, -2201.88, 6.0), radius = 9.0},
    {coords = vector3(-743.1, -2193.75, 5.01), radius = 7.0},
    {coords = vector3(-751.14, -2188.25, 5.0), radius = 6.0},
    {coords = vector3(-757.61, -2191.97, 5.0), radius = 8.0},
    {coords = vector3(-763.69, -2199.19, 5.0), radius = 6.5},
    {coords = vector3(-771.38, -2208.22, 5.0), radius = 6.5},
    {coords = vector3(-762.01, -2205.41, 5.0), radius = 5.0},
    {coords = vector3(-777.68, -2216.09, 5.0), radius = 7.0},
    {coords = vector3(-782.92, -2222.06, 5.0), radius = 5.0},
}

Config.Examiner = {
    Enabled = true, -- Do you want to use a ped as an examiner who sits with the player in the vehicle?
    SpokenCommands = true,
    SpokenLanguage = "EN", -- "EN", "DE", "BG", "ES", "FR", "PT"
    PedModel = 'ig_fbisuit_01' -- https://wiki.rage.mp/index.php?title=Peds
}

local licensesResourceAutoFind = function()
    if GetResourceState('Buty-license') == 'started' then
        return "buty-license"
    else
        return "default"
    end
end
--[[
    Supported Licenses script:
    - Buty-license
    - esx_license (default)
    - qb-core metadata (default)
]]
Config.LicensesResource = licensesResourceAutoFind()

---@field AddLicenseItem boolean: Do you use your drivers license as an item on the server
Config.AddLicenseItem = false
Config.LicenseItem = "driving_license"

Config.MenuIcon = ''
Config.Licenses = {
    Theory = {
        ['A'] = {name = 'theory_a', price = 150, menuIcon = 'far fa-file-alt', enabled = true},
        ['B'] = {name = 'theory_b', price = 300, menuIcon = 'far fa-file-alt', enabled = true},
        ['C'] = {name = 'theory_c', price = 450, menuIcon = 'far fa-file-alt', enabled = true}
    },
    Practical = {
        ['A'] = {name = Config.LicensesResource == "buty-license" and 'motorcycle' or 'drive_a', price = 2500, menuIcon = 'fas fa-motorcycle', enabled = true},
        ['B'] = {name = Config.LicensesResource == "buty-license" and 'car' or 'drive_b', price = 4500, menuIcon = 'fas fa-car-side', enabled = true},
        ['C'] = {name = Config.LicensesResource == "buty-license" and 'truck' or 'drive_c', price = 6500, menuIcon = 'fas fa-truck', enabled = true}
    }
}

Config.Questions = {
    ['A'] = {
        QuestionsCount = 18, -- Number of all questions for the draw pool
        QuestionToAnswer = 18, -- Questions the player will have to answer
        NeedAnswersToPass = 16, -- Number of questions a player must answer correctly to pass the theory exam
    },
    ['B'] = {
        QuestionsCount = 17,
        QuestionToAnswer = 17,
        NeedAnswersToPass = 15,
    },
    ['C'] = {
        QuestionsCount = 5,
        QuestionToAnswer = 5,
        NeedAnswersToPass = 4,
    },
}

Config.Tasks = {
    {label = "Start the engine", id = 1}, 
    -- DE: Starte den Motor
    -- BG: Стартирайте двигателя
    -- ES: Encender el motor
    -- FR: Démarre le moteur
    -- PT: Ligue o Motor
    -- PL: Uruchom silnik

    {label = "Turn on the lights", id = 2}, 
    -- DE: Schalte die Scheinwerfer ein
    -- BG: Включете светлените на автомобила
    -- ES: Enciende las luces
    -- FR: Allume les phares
    -- PT: Ligue as luzes
    -- PL: Włącz światła

    {label = "Get on the elevation", id = 3}, 
    -- DE: Fahre die Rampe hoch
    -- BG: Качете се на височината
    -- ES: Sube a la elevación
    -- FR: Monte sur la plateforme
    -- PT: Dirija-se para a rampa
    -- PL: Wjedź na wzniesienie

    {label = "Park at the rear slant", id = 4}, 
    -- DE: Parke in die Parklücke ein
    -- BG: Паркирайте на задния наклон
    -- ES: Parquea en la inclinación trasera
    -- FR: Gare toi en biais arrière
    -- PT: Estacione de marcha-atrás
    -- PL: Zaparkuj pod skosem tyłem
    
    {label = "Park parallel in front", id = 5}, 
    -- DE: Parke dort in Fahrtrichtung ein
    -- BG: Паркирайте успоредно отпред
    -- ES: Parquea paralelo en el frente
    -- FR: Gare toi en parallèle à l'avant
    -- PT: Estacione paralelamente de frente
    -- PL: Zaparkuj równolegle przodem
    
    -- {label = "ID 6 HAVE NO SPECIAL MANEUVERS", id = 6},
    
    {label = "Park parallel backwards", id = 7}, 
    -- DE: Parke rückwärts ein
    -- BG: Паркирайте успоредно отзад
    -- ES: Parquea paralelo al revés
    -- FR: Gare toi en parallèle à l'arrière
    -- PT: Estacione paralelamente de marcha-atrás
    -- PL: Zaparkuj równolegle tyłem
    
    {label = "Leave the maneuvering area", id = 8}, 
    -- DE: Verlasse den Verkehrsübungsplatz
    -- BG: Напуснете зоната за маневриране
    -- ES: Deja el área de maniobra
    -- FR: Quitte la zone de manœuvre
    -- PT: Saia da zona de manobras
    -- PL: Opuść plac manewrowy
    
    {label = "Get on a public road", id = 9}, 
    -- DE: Fahre auf die Straße
    -- BG: Поставете се на обществен път
    -- ES: Sube a una carretera pública
    -- FR: Emprunte une route publique
    -- PT: Entre na estrada
    -- PL: Wyjedź na drogę publiczną
    
    {label = "Stop before the lanes", id = 10}, 
    -- DE: Halte am Stoppschild
    -- BG: Спрете преди лентaтa за движение
    -- ES: Detente antes de los carriles
    -- FR: Arrête-toi avant le passage piéton
    -- PT: Pare antes da linha
    -- PL: Zatrzymaj się przed pasami
    
    {label = "Free ride <span>0.00</span>km / 2.00km", id = 11},
    
    {label = "Go back to driving school", id = 12}, 
    -- DE: Fahre zurück zur Fahrschule
    -- BG: Върнете се в автошколата
    -- ES: Volver a la escuela de conducción
    -- FR: Retourne à l'école de conduite
    -- PT: Volte para a escola de condução
    -- PL: Wróć do szkoły jazdy
}

Config.Zones = {
    ["menu"] = {
        menuType = "qb-menu", -- "esx_menu_default" / "esx_context" / "qb-menu" / "ox_lib"
        menuPosition = 'left', -- only for esx_menu_default and esx_context
        coords = vector3(-893.67, -2402.06, 14.125),
        marker = {
            id = 36, -- https://docs.fivem.net/docs/game-references/markers/
            color = {115, 255, 115, 120}, -- R(ed), G(reen), B(lue), A(lpha)
            scale = vec(0.65, 0.65, 0.65),
            bobUpAndDown = false, -- jumping marker
            rotate = true -- rotating marker
        },
        blip = { -- https://docs.fivem.net/docs/game-references/blips/
            sprite = 778,
            display = 4,
            scale = 1.0,
            color = 43,
            name = "Driving School"
        }
    },
    ["return_vehicle"] = {
        coords = vector3(-890.08, -2377.37, 12.94),
        marker = {
            id = 1, -- https://docs.fivem.net/docs/game-references/markers/
            color = {255, 0, 0, 120}, -- R(ed), G(reen), B(lue), A(lpha)
            scale = vec(1.5, 1.5, 0.75),
            bobUpAndDown = false, -- jumping marker
            rotate = true -- rotating marker
        },
        blip = { -- https://docs.fivem.net/docs/game-references/blips/
            sprite = 467,
            display = 4,
            scale = 1.0,
            color = 2,
            routeColor = 2,
            name = "Return to Drive School"
        }
    }
}

Config.Practical = {
    ['Vehicles'] = { -- https://docs.fivem.net/docs/game-references/vehicle-models/
        A = 'pcj',
        B = 'premier',
        C = 'boxville_vms',
    },
    ['Marker'] = { -- https://docs.fivem.net/docs/game-references/markers/
        id = 20, 
        size = vec(0.35, 0.35, 0.35),
        rotate = {0.0, 180.0, 0.0},
        rgba = {255, 255, 0, 140},
        rotataing = true
    },
    ['Blip'] = { -- https://docs.fivem.net/docs/game-references/blips/
        sprite = 270,
        display = 4,
        scale = 0.8,
        color = 28,
        routeColor = 28,
        name = "Point"
    },
    ['SpawnPoint'] = vector4(-723.38, -2210.23, 4.9, 49.79),
}

Config.PracticalTest = { -- if you don't know what each action does, don't touch it to avoid spoiling the exam route
    [1] = {
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_1.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myPed = PlayerPedId()
                    local myVehicle = GetVehiclePedIsIn(myPed, false)
                    if GetIsVehicleEngineRunning(myVehicle) then
                        SetVehicleLightsMode(myVehicle, 1)
                        SendNUIMessage({action = 'updateTasks', done = 1})
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [2] = {
        action = function()
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myPed = PlayerPedId()
                    local myVehicle = GetVehiclePedIsIn(myPed, false)
                    local _, lights, highbeams = GetVehicleLightsState(myVehicle)
                    if lights then
                        setBlipToPoint(3)
                        SendNUIMessage({action = 'updateTasks', done = 2})
                        FreezeEntityPosition(myVehicle, false)
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [3] = {
        coords = vector3(-732.03, -2202.92, 6.49),
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_3.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myPed = PlayerPedId()
                    local myVehicle = GetVehiclePedIsIn(myPed, false)
                    local myCoords = GetEntityCoords(myVehicle)
                    local current = Config.PracticalTest[3]
                    local distance = #(myCoords - current.coords)
                    DrawMarker(Config.Practical['Marker'].id, vec(current.coords.x, current.coords.y, current.coords.z+2.0), 0.0, 0.0, 0.0, Config.Practical['Marker'].rotate[1], Config.Practical['Marker'].rotate[2], Config.Practical['Marker'].rotate[3],  Config.Practical['Marker'].size, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    DrawMarker(1, vec(current.coords.x, current.coords.y, current.coords.z-0.35), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Practical['Marker'].size*1.5, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    if distance < 1.5 then
                        setBlipToPoint(4)
                        FreezeEntityPosition(myVehicle, true)
                        Citizen.Wait(2000)
                        FreezeEntityPosition(myVehicle, false)
                        SendNUIMessage({action = 'updateTasks', done = 3})
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [4] = {
        coords = vector3(-763.08, -2205.39, 5.2),
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_4.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myCoords = GetEntityCoords(PlayerPedId())
                    local current = Config.PracticalTest[4]
                    local distance = #(myCoords - current.coords)
                    DrawMarker(Config.Practical['Marker'].id, vec(current.coords.x, current.coords.y, current.coords.z+2.0), 0.0, 0.0, 0.0, Config.Practical['Marker'].rotate[1], Config.Practical['Marker'].rotate[2], Config.Practical['Marker'].rotate[3],  Config.Practical['Marker'].size, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    DrawMarker(1, vec(current.coords.x, current.coords.y, current.coords.z-0.25), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Practical['Marker'].size*1.5, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    if distance < 1.5 then
                        setBlipToPoint(5)
                        SendNUIMessage({action = 'updateTasks', done = 4})
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [5] = {
        coords = vector4(-774.34, -2215.93, 5.2, 141.49),
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_5.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myPed = PlayerPedId()
                    local myVehicle = GetVehiclePedIsIn(myPed, false)
                    local myCoords = GetEntityCoords(myVehicle)
                    local current = Config.PracticalTest[5]
                    local distance = #(myCoords - vec(current.coords.x, current.coords.y, current.coords.z))
                    DrawMarker(Config.Practical['Marker'].id, vec(current.coords.x, current.coords.y, current.coords.z+2.0), 0.0, 0.0, 0.0, Config.Practical['Marker'].rotate[1], Config.Practical['Marker'].rotate[2], Config.Practical['Marker'].rotate[3],  Config.Practical['Marker'].size, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    DrawMarker(1, vec(current.coords.x, current.coords.y, current.coords.z-0.25), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Practical['Marker'].size*1.5, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    if distance < 1.5 then
                        setBlipToPoint(6)
                        SetEntityCoords(myVehicle, current.coords.x, current.coords.y, current.coords.z)
                        SetEntityHeading(myVehicle, current.coords.w)
                        SendNUIMessage({action = 'updateTasks', done = 5})
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [6] = {
        coords = vector3(-782.78, -2221.99, 5.2),
        action = function()
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myCoords = GetEntityCoords(PlayerPedId())
                    local current = Config.PracticalTest[6]
                    local distance = #(myCoords - current.coords)
                    DrawMarker(Config.Practical['Marker'].id, vec(current.coords.x, current.coords.y, current.coords.z+2.0), 0.0, 0.0, 0.0, Config.Practical['Marker'].rotate[1], Config.Practical['Marker'].rotate[2], Config.Practical['Marker'].rotate[3],  Config.Practical['Marker'].size, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    DrawMarker(1, vec(current.coords.x, current.coords.y, current.coords.z-0.25), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Practical['Marker'].size*1.5, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    if distance < 1.5 then
                        setBlipToPoint(7)
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [7] = {
        coords = vector4(-775.85, -2217.02, 5.2, 138.45),
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_7.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do
                if GetVehiclePedIsIn(PlayerPedId()) == currentDriveVehicle and GetPedInVehicleSeat(currentDriveVehicle, -1) == PlayerPedId() then
                    local myPed = PlayerPedId()
                    local myVehicle = GetVehiclePedIsIn(myPed, false)
                    local myCoords = GetEntityCoords(myVehicle)
                    local current = Config.PracticalTest[7]
                    local distance = #(myCoords - vec(current.coords.x, current.coords.y, current.coords.z))
                    DrawMarker(Config.Practical['Marker'].id, vec(current.coords.x, current.coords.y, current.coords.z+2.0), 0.0, 0.0, 0.0, Config.Practical['Marker'].rotate[1], Config.Practical['Marker'].rotate[2], Config.Practical['Marker'].rotate[3],  Config.Practical['Marker'].size, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    DrawMarker(1, vec(current.coords.x, current.coords.y, current.coords.z-0.25), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Practical['Marker'].size*1.5, Config.Practical['Marker'].rgba[1], Config.Practical['Marker'].rgba[2], Config.Practical['Marker'].rgba[3], Config.Practical['Marker'].rgba[4], false, false, false, Config.Practical['Marker'].rotataing, false, false, false)
                    if distance < 1.5 then
                        setBlipToPoint(8)
                        SetEntityCoords(myVehicle, current.coords.x, current.coords.y, current.coords.z)
                        SetEntityHeading(myVehicle, current.coords.w)
                        SendNUIMessage({action = 'updateTasks', done = 7})
                        break
                    end
                end
                Citizen.Wait(1)
            end
        end
    },
    [8] = {
        coords = vector3(-713.93, -2224.48, 5.1),
        action = function()
            if Config.Examiner.SpokenCommands and driveErrors < Config.MaxDriveErrors then
                SendNUIMessage({action = 'audioTask', filename = string.lower(Config.Examiner.SpokenLanguage)..'_8.mp3'})
            end
            while currentExam and driveErrors < Config.MaxDriveErrors do