Configuration

Don't touch this line

Config, Blips, Lang, Noti, Vehicles, TheoricalInstructor, PracticeInstructor, TheoricalUserPosition, Receptionist = {},
    {}, {}, {}, {}, {}, {}, {}, {}

CONFIGURATION FILE

Config, Blips, Lang, Noti, Vehicles, TheoricalInstructor, PracticeInstructor, TheoricalUserPosition, Receptionist = {},
    {}, {}, {}, {}, {}, {}, {}, {}

-- Trigger to open menu:
-- TriggerClientEvent("bit-boatschool:openMenu")

-- Trigger to delete license:
-- TriggerServerEvent("bit-boatschool:deleteLicense", playerID, license)

--  a88888b.  .88888.  888888ba   88888888b dP  .88888.  dP     dP  888888ba   .d888888  d888888P dP  .88888.  888888ba  
-- d8'   `88 d8'   `8b 88    `8b  88        88 d8'   `88 88     88  88    `8b d8'    88     88    88 d8'   `8b 88    `8b 
-- 88        88     88 88     88 a88aaaa    88 88        88     88 a88aaaa8P' 88aaaaa88a    88    88 88     88 88     88 
-- 88        88     88 88     88  88        88 88   YP88 88     88  88   `8b. 88     88     88    88 88     88 88     88 
-- Y8.   .88 Y8.   .8P 88     88  88        88 Y8.   .88 Y8.   .8P  88     88 88     88     88    88 Y8.   .8P 88     88 
--  Y88888P'  `8888P'  dP     dP  dP        dP  `88888'  `Y88888P'  dP     dP 88     88     dP    dP  `8888P'  dP     dP

-- Use "esx" or "qb"
Config.Framework = "qb"
-- If you are using one of the most recent versions of ESX, set the script name. Default = "es_extended"
Config.ESXExport = ""
-- Default ESX: "esx:getSharedObject" | Default QB: "qb-core"
Config.Core = "qb-core"
-- oxmysql, mysql-async or ghmattisql
Config.Mysql = "oxmysql"
-- A license price
Config.licenseBoatPrice = 2500
-- B license price
Config.licenseYachtPrice = 5500
-- Number of questions for the theoretical test
Config.theoricalTotalQuestions = 9
-- Answers needed to pass the theory test
Config.correctAnswersNeeded = 5
-- Boat license name in the database
Config.licenseNameBoat = 'boat'
-- Yacht license name in the database
Config.licenseNameYach = 'yacht'
-- Instructor audio language. Change it or replace the files in the audio folder
Config.TTSLanguage = 'EN'
-- Maximum number of errors that can be made in the practical test
Config.MaxErrorsPractice = 5
-- Font used in alerts. Set to 0 if your language is Chinese
Config.alertTextFont = 4
-- Set to true if you want to use ESX.DeleteVehicle or QBCore.Functions.DeleteVehicle. If set to false, the native function will be used.
Config.UseEsxQBDeleteVehicle = false
-- Check license in the database
Config.checkDBLicense = true
-- Teleport the user to the driving school if he fails the practical test
Config.teleportIfFails = true
-- Coordinates to teleport the user if fails the practical test
Config.teleportIfFailsCoord = vector3(-714.29, -1297.32, 5.1)
-- Check if there is a vehicle at spawn point
Config.checkspawnpoint = true
-- Account to which you want the money to be charged
Config.accountToRemoveMoney = "bank"
-- Set to true if you want users to have to repeat the theory for each license
Config.repeatTheorical = true

-- dP     dP  88888888b dP    dP .d88888b  
-- 88   .d8'  88        Y8.  .8P 88.    "' 
-- 88aaa8P'  a88aaaa     Y8aa8P  `Y88888b. 
-- 88   `8b.  88           88          `8b 
-- 88     88  88           88    d8'   .8P 
-- dP     dP  88888888P    dP     Y88888P

Config.useKeys = true

function addKeys(vehicle)
    -- Insert here your trigger. EX:
    -- TriggerServerEvent("keyscar:server:addKey", GetVehicleNumberPlateText(vehicle), false)
end

function removeKeys(vehicle, plate)
    if vehicle ~= 0 and plate ~= nil then
        -- Insert here your trigger
    end
end

-- dP     dP  88888888b dP     dP  dP  a88888b. dP         88888888b .d88888b  
-- 88     88  88        88     88  88 d8'   `88 88         88        88.    "' 
-- 88    .8P a88aaaa    88aaaaa88a 88 88        88        a88aaaa    `Y88888b. 
-- 88    d8'  88        88     88  88 88        88         88              `8b 
-- 88  .d8P   88        88     88  88 Y8.   .88 88         88        d8'   .8P 
-- 888888'    88888888P dP     dP  dP  Y88888P' 88888888P  88888888P  Y88888P

Vehicles.boat = 'dinghy'
Vehicles.yacht = 'marquis'
Vehicles.spawn = {
    x = -735.26,
    y = -1380.42,
    z = 0.44,
    heading = 139.91
}

-- 88888888b dP     dP  88888888b dP        
-- 88        88     88  88        88        
-- a88aaaa    88     88 a88aaaa    88        
-- 88        88     88  88        88        
-- 88        Y8.   .8P  88        88        
-- dP        `Y88888P'  88888888P 88888888P

-- set to true if you want to use a custom fuel script
Config.useCustomFuel = false

function setFuel(vehicle)

end

-- 888888ba   888888ba   a88888b. 
-- 88    `8b  88    `8b d8'   `88 
-- 88     88 a88aaaa8P' 88        
-- 88     88  88        88        
-- 88     88  88        Y8.   .88 
-- dP     dP  dP         Y88888P'

Receptionist.npc = 's_f_y_airhostess_01'
Receptionist.x = -712.66
Receptionist.y = -1298.15
Receptionist.z = 5.1
Receptionist.heading = 34.38

PracticeInstructor.use = true
PracticeInstructor.npc = 's_m_m_pilot_01'
PracticeInstructor.x = -708.16
PracticeInstructor.y = -1356.4
PracticeInstructor.z = 1.6
PracticeInstructor.heading = 42.01
-- if you want the npc to spawn directly inside the vehicle
PracticeInstructor.useTeleport = true

TheoricalInstructor.npc = 'csb_reporter'
TheoricalInstructor.x = 0.0
TheoricalInstructor.y = 0.0
TheoricalInstructor.z = 0.0
TheoricalInstructor.heading = 0.0

TheoricalUserPosition.x = -715.01
TheoricalUserPosition.y = -1297.58
TheoricalUserPosition.z = 5.1
TheoricalUserPosition.heading = 46.49

-- 888888ba   .88888.  d888888P dP  88888888b dP  a88888b.  .d888888  d888888P dP  .88888.  888888ba  .d88888b  
-- 88    `8b d8'   `8b    88    88  88        88 d8'   `88 d8'    88     88    88 d8'   `8b 88    `8b 88.    "' 
-- 88     88 88     88    88    88 a88aaaa    88 88        88aaaaa88a    88    88 88     88 88     88 `Y88888b. 
-- 88     88 88     88    88    88  88        88 88        88     88     88    88 88     88 88     88       `8b 
-- 88     88 Y8.   .8P    88    88  88        88 Y8.   .88 88     88     88    88 Y8.   .8P 88     88 d8'   .8P 
-- dP     dP  `8888P'     dP    dP  dP        dP  Y88888P' 88     88     dP    dP  `8888P'  dP     dP  Y88888P

function notifications(notitype, message, time)
    -- Change this trigger for your notification system keeping the variables
    TriggerEvent('codem-notification', message, time, notitype)
end

-- Notifications types:
Noti.info = 'info'
Noti.check = 'check'
Noti.error = 'error'

-- Notification time:
Noti.time = 5000

--  888888ba  dP        dP  888888ba  .d88888b  
--  88    `8b 88        88  88    `8b 88.    "' 
-- a88aaaa8P' 88        88 a88aaaa8P' `Y88888b. 
--  88   `8b. 88        88  88              `8b 
--  88    .88 88        88  88        d8'   .8P 
--  88888888P 88888888P dP  dP         Y88888P

Blips.active = true
Blips.coord = {
    x = -712.66,
    y = -1298.15,
    z = 5.1
}
Blips.blip = 410
Blips.blipColor = 2
Blips.blipScale = 0.9
Blips.blipText = "Boat School"

-- 8888ba.88ba   .d888888   888888ba  dP     dP  88888888b  888888ba  .d88888b  
-- 88  `8b  `8b d8'    88   88    `8b 88   .d8'  88         88    `8b 88.    "' 
-- 88   88   88 88aaaaa88a a88aaaa8P' 88aaa8P'  a88aaaa    a88aaaa8P' `Y88888b. 
-- 88   88   88 88     88   88   `8b. 88   `8b.  88         88   `8b.       `8b 
-- 88   88   88 88     88   88     88 88     88  88         88     88 d8'   .8P 
-- dP   dP   dP 88     88   dP     dP dP     dP  88888888P  dP     dP  Y88888P

Marker = {
    x = -712.66,
    y = -1298.15,
    z = 5.1,
    mtype = 23,
    -- RGB COLOR:
    r = 39,
    g = 233,
    b = 140,
    -- DISTANCE AND SIZE:
    dis = 3,
    size = 2.0
}

--  888888ba   .88888.  dP     dP d888888P  88888888b 
--  88    `8b d8'   `8b 88     88    88     88        
-- a88aaaa8P' 88     88 88     88    88    a88aaaa    
--  88   `8b. 88     88 88     88    88     88        
--  88     88 Y8.   .8P Y8.   .8P    88     88        
--  dP     dP  `8888P'  `Y88888P'    dP     88888888P

Routes = {
    [1] = {
        x = -855.75,
        y = -1550.42,
        z = -0.07
    },
    [2] = {
        x = -1269.23,
        y = -1955.04,
        z = 0.52
    },
    [3] = {
        x = -1682.78,
        y = -2303.46,
        z = 0.16
    },
    [4] = {
        x = -1931.5,
        y = -2713.39,
        z = -0.62
    },
    [5] = {
        x = -2166.34,
        y = -2916.78,
        z = 0.47
    },
    [6] = {
        x = -2007.04,
        y = -2403.79,
        z = 0.32
    },
    [7] = {
        x = -1538.4,
        y = -2134.44,
        z = 0.84
    },
    [8] = {
        x = -1088.71,
        y = -1791.22,
        z = 0.22
    },
    [9] = {
        x = -737.99,
        y = -1375.75,
        z = -0.12
    }
}

--  .88888.   dP     dP  88888888b .d88888b  d888888P dP  .88888.  888888ba  .d88888b  
-- d8'   `8b  88     88  88        88.    "'    88    88 d8'   `8b 88    `8b 88.    "' 
-- 88     88  88     88 a88aaaa    `Y88888b.    88    88 88     88 88     88 `Y88888b. 
-- 88  db 88  88     88  88              `8b    88    88 88     88 88     88       `8b 
-- Y8.  Y88P  Y8.   .8P  88        d8'   .8P    88    88 Y8.   .8P 88     88 d8'   .8P 
--  `8888PY8b `Y88888P'  88888888P  Y88888P     dP    dP  `8888P'  dP     dP  Y88888P

Questions = {
    ['What should you do if you see a pirate on the horizon?'] = {
        [1] = 'Hoist the black flag and prepare the cannons',
        [2] = 'Call the coast guard',
        [3] = 'Invite them to a costume party',
        ['correct'] = 2,
        ['index'] = 1
    },
    ['What is the maximum speed allowed in a manatee zone?'] = {
        [1] = '5 knots',
        [2] = 'As fast as you can before they see you',
        [3] = 'Depends on if the manatees are in a good mood',
        ['correct'] = 1,
        ['index'] = 2
    },
    ["What does it mean if the ship's flag is flying upside down?"] = {
        [1] = "It's nap time for the crew",
        [2] = "We're having a garage sale",
        [3] = 'Signal of distress',
        ['correct'] = 3,
        ['index'] = 3
    },
    ['How can you prevent seasickness?'] = {
        [1] = 'By staring at the horizon while dancing salsa',
        [2] = 'Keeping your eyes on the horizon and avoiding sudden movements',
        [3] = 'Challenging the sea to a staring contest',
        ['correct'] = 2,
        ['index'] = 4
    },
    ["What's the best method to repel sharks?"] = {
        [1] = 'Negotiate peacefully with them',
        [2] = 'Invite them to a game of water volleyball',
        [3] = 'Use a specialized shark repellent',
        ['correct'] = 3,
        ['index'] = 5
    },
    ['What do you do if your boat starts sinking?'] = {
        [1] = 'Take selfies for Instagram',
        [2] = 'Quickly organize a swimming contest',
        [3] = 'Use safety equipment and call for help',
        ['correct'] = 3,
        ['index'] = 6
    },
    ['How do you greet another boat at sea?'] = {
        [1] = 'Using flag signals or radio',
        [2] = 'With fireworks and loud music',
        [3] = 'Doing the wave',
        ['correct'] = 1,
        ['index'] = 7
    },
    ['What should you check before setting sail?'] = {
        [1] = "If there's enough ice for the drinks",
        [2] = 'The weather conditions and the condition of the boat',
        [3] = 'That everyone on board has been to the bathroom',
        ['correct'] = 2,
        ['index'] = 8
    },
    ["What's the most important rule when steering a boat?"] = {
        [1] = "Always wear a captain's hat",
        [2] = 'Stay sober and alert',
        [3] = 'Make sure the music never stops',
        ['correct'] = 2,
        ['index'] = 9
    }

}

-- dP         .d888888  888888ba   .88888.  dP     dP  .d888888   .88888.   88888888b 
-- 88        d8'    88  88    `8b d8'   `88 88     88 d8'    88  d8'   `88  88        
-- 88        88aaaaa88a 88     88 88        88     88 88aaaaa88a 88        a88aaaa    
-- 88        88     88  88     88 88   YP88 88     88 88     88  88   YP88  88        
-- 88        88     88  88     88 Y8.   .88 Y8.   .8P 88     88  Y8.   .88  88        
-- 88888888P 88     88  dP     dP  `88888'  `Y88888P' 88     88   `88888'   88888888P

Lang.theoricalneeded = "You must take the theoretical test before taking the practical test"
Lang.returnvehicule = "Return to the vehicle. The test will be cancelled in 10 seconds"
Lang.testcanceled = "The test has been cancelled. Retest again"
Lang.approved = "Congratulations, you have passed!"
Lang.suspended = "You have failed, you can try again another time."
Lang.passed = "You have already passed this test, you cannot take it again"
Lang.enter = "Press ~g~E~w~ to access the ~g~boat school"
Lang.deletedLicense = "The license has been successfully removed"
Lang.noMoney = "You don't have enough money"
Lang.occupiedSpace = "The space to take the vehicle out of the boat school is occupied"

Config.useCustomDrawTxt = true

function customDrawTxt()
    TriggerEvent("bit-interact:Start", "E", "Press to access the boat school")
end

--  88888888b dP     dP 888888ba   a88888b. d888888P dP  .88888.  888888ba  .d88888b  
--  88        88     88 88    `8b d8'   `88    88    88 d8'   `8b 88    `8b 88.    "' 
-- a88aaaa    88     88 88     88 88           88    88 88     88 88     88 `Y88888b. 
--  88        88     88 88     88 88           88    88 88     88 88     88       `8b 
--  88        Y8.   .8P 88     88 Y8.   .88    88    88 Y8.   .8P 88     88 d8'   .8P 
--  dP        `Y88888P' dP     dP  Y88888P'    dP    dP  `8888P'  dP     dP  Y88888P

-- Function to add licenses to the user

function applyLicense(xPlayer, license)
    if Config.Framework == "esx" then
        if license == 'A' then
            SqlFunc(Config.Mysql, 'execute', 'INSERT INTO user_licenses (type, owner) VALUES (@type, @owner)', {
                ['@type'] = Config.licenseNameHelicopter,
                ['@owner'] = xPlayer.identifier
            })
        elseif license == 'B' then
            SqlFunc(Config.Mysql, 'execute', 'INSERT INTO user_licenses (type, owner) VALUES (@type, @owner)', {
                ['@type'] = Config.licenseNamePlane,
                ['@owner'] = xPlayer.identifier
            })
        end
    elseif Config.Framework == "qb" then
        if license == 'A' then
            local licenseTable = xPlayer.PlayerData.metadata['licences']
            licenseTable[Config.licenseNameHelicopter] = true
            xPlayer.Functions.SetMetaData('licences', licenseTable)
            xPlayer.Functions.AddItem('driver_license', 1)
        elseif license == 'B' then
            local licenseTable = xPlayer.PlayerData.metadata['licences']
            licenseTable[Config.licenseNamePlane] = true
            xPlayer.Functions.SetMetaData('licences', licenseTable)
        end
    end
end

function deleteLicense(xPlayer)
    if Config.Framework == "esx" then
        SqlFunc(Config.Mysql, 'execute', 'DELETE FROM bit_boatschool WHERE userIdentifier = @userIdentifier', {
            ['@userIdentifier'] = xPlayer.identifier
        })
        SqlFunc(Config.Mysql, 'execute',
            'DELETE FROM user_licenses WHERE owner = @owner and type = ' .. Config.licenseNameHelicopter .. ' or type = ' ..
                Config.licenseNamePlane, {
                ['@owner'] = xPlayer.identifier
            })
        notifications(Noti.check, Lang.deletedLicense, Noti.time)
    elseif Config.Framework == "qb" then
        local licenseTable = xPlayer.PlayerData.metadata['licences']
        licenseTable[Config.licenseNameHelicopter] = false
        licenseTable[Config.licenseNamePlane] = false
        xPlayer.Functions.SetMetaData('licences', licenseTable)
        SqlFunc(Config.Mysql, 'execute', 'DELETE FROM bit_boatschool WHERE userIdentifier = @userIdentifier', {
            ['@userIdentifier'] = xPlayer.identifier
        })
        notifications(Noti.check, Lang.deletedLicense, Noti.time)
    end
end

Last updated