[ESX/QB/STANDALONE] Trucker Job

truckerjob

:truck: Trucker job

Do you want to bring the trucker-life to your server and are you looking for something unique? With this highly configurable trucker job, you pickup and deliver cargo to designated locations, where you have to carefully park the cargo at a specified location.

:shopping_cart: Get it here: gamzkystore.com

:question: Support: Discord

:movie_camera: Detailed Preview:

Features

  • This script can be run as a standalone script, but is preconfigured to work for ox-target, esx, qb-core and qb-target.
  • A configurable truck-rent is present and optional, as it is also possible to carry out the job with personally owned vehicles.
  • All interactions, like starting the job, renting a truck or pickup up cargo goes via NPCs which respond to your actions via GTA voice lines, resulting in an immersive experience.
  • A single job consists of multiple (amount is configurable) routes where you pickup and deliver cargo.
  • The cargo cannot be simply dropped off, the player will have to correctly park the cargo in the designated area.
  • After a player has finished a complete route, he can instantly start a new route, so the players are not forced to go all the way back to the starting location but can continue right away with the job.
  • Optimized to always run at 0 ms, only when the parking location has to be displayed will it run at a mere 0,06 ms.
  • A debug-mode is available, which enables the use of the command /cargobox. This will make it easy to add new pickup and delivery locations to the script with a single mouse-click.
  • The normal version is encrypted, but key functions are still accessible via bridge code. See the code snippets below for all accessible code.
Config
Config = {}

-- The amount of routes the player has to drive
Config.AmountOfRoutes = 3

-- The minimum distance between the pickup and delivery location
Config.MinimumDistanceBetweenPickupAndDelivery = 500

-- The money the player receives when completing all delivery routes
Config.Reward = 1000

-- By default, the cargo entity is set as 'no longer needed', which means it will be automatically deleted when all players go away. If you want the cargo to be deleted instantly when delivered, set this to true
Config.DeleteCargoOnDelivery = false

-- The margin of error for the parking distance, increase to make parking easier
Config.ParkingDistanceMargin = 1.0

Config.Start = {
    -- The coordinates where the player will start the job, the last entry is the heading
    Coords = vector4(-1148.00, -2178.78, 12.38, 64.78),

    -- The coordinates where the vehicle will spawn, the last entry is the heading
    VehicleSpawnCoords = vector4(-1155.57, -2175.23, 13.45, 140.93),

    -- The radius around the vehicle spawn coordinates that has to be clear of all vehicles, set to 0 to disable
    ClearSpawnRadius = 5.0,

    -- The ped that where you can start the job, and also where you pickup cargo
    Ped = {
        Model = { 's_m_m_trucker_01', 's_m_m_ups_01', 's_m_m_dockwork_01', 'ig_floyd', 'cs_josef' },                          -- The model of the ped, randomly chosen from the table
        Scenario = { 'WORLD_HUMAN_CLIPBOARD' },                                                                               -- The scenario the ped will play, randomly chosen from the table
        VoiceName = { 'S_M_M_TRUCKER_01_WHITE_FULL_01', 'S_M_M_TRUCKER_01_WHITE_FULL_02', 'S_M_M_TRUCKER_01_BLACK_FULL_01' }, -- The possible voice names of the ped
        GreetLines = { 'GENERIC_HI', 'GENERIC_HOWS_IT_GOING' },                                                               -- The possible lines the ped will say when you interact with it
        FailedLines = { 'GENERIC_WHATEVER' },                                                                                 -- The possible lines the ped will say when you interact with it and the spawn is not clear
        GoodbyeLines = { 'GENERIC_BYE' },                                                                                     -- The possible lines the ped will say when you stop the job
    },

    -- The blip that will be shown on the map
    Blip = {
        Enabled = true,            -- Set to false to disable the blip
        Sprite = 477,              -- The sprite of the blip
        Color = 26,                -- The color of the blip
        Scale = 1.1,               -- The scale of the blip
        BlipLabel = 'Trucker Job', -- The label of the blip
    },
}

Config.CargoBlip = {
    Sprite = 615, -- The sprite of the blip
    Color = 5,    -- The color of the blip
    Scale = 0.8,  -- The scale of the blip
}

-- The configuration for truck renting
Config.Truck = {
    Enable = true, -- Set to false to disable the truck rental

    -- The possible models of the truck, chosen randomly from the table
    Models = { 'hauler', 'packer', 'phantom' },

    -- The deposit the player has to pay to rent a truck, set to 0 to disable
    Deposit = 1000,

    -- The cooldown in seconds before the player can rent another truck, the cooldown resets if a player (attempts) to return a truck. Set to zero to disable
    Cooldown = 300,
}

-- After completing the truckerjob, you can configure the option to allow the player to start another trucker job right away with the click of a button, without having to drive back to the starting npc
Config.Restart = {
    Enable = true,                                                                                       -- Set to false to disable the instant restart after completing all delivery routes
    Key = 80,                                                                                            -- The key to press to start a new trucker job right away, by default this is 'R'
    HelpText = 'All deliveries complete, you can press [~b~R~s~] to start a new trucker job right away', -- The text that is displayed to the player when they can press the configured key
    TimeToRestart = 20,                                                                                  -- The amount of seconds someone has, to press the configured button to start a new trucker job right away
}

-- The possible coordinates where the player can pickup and deliver the cargo, the last entry for each vector4 is the heading
-- When adding locations, be sure to set Config.Debug to true and use the /cargobox command to easily add new coordinates
Config.Coords = {
    Cargo = {
        { Pickup = vector4(-1095.45, -2036.24, 12.29, 90.00),  Spawn = vector4(-1102.52, -2039.78, 13.29, 315.00), CargoModels = { 'trailers', 'trailers2', 'trailers3' } },
        { Pickup = vector4(-1069.99, -2013.77, 12.16, 270.00), Spawn = vector4(-1062.92, -2010.24, 13.16, 135.00), CargoModels = { 'trailers', 'trailers2', 'trailers3' } },
        { Pickup = vector4(-832.57, -2676.17, 12.81, 15.00),   Spawn = vector4(-837.81, -2670.25, 13.81, 240.00),  CargoModels = { 'docktrailer', 'trailers', 'trailers2', 'trailers3' } },
        -- Rest of the locations left out for readability...
    },
    CargoDelivery = {
        vector4(-1071.02, -2072.68, 12.29, 315.00),
        vector4(-1052.25, -2020.63, 12.16, 135.00),
        vector4(-1031.02, -2219.10, 7.98, 225.00),
        -- Rest of the locations left out for readability...
    }
}

-- Text interactions displayed to the player
Config.Locales = {
    ['start_job_text'] = 'Start trucker job',
    ['stop_job_text'] = 'Stop trucker job',
    ['rent_truck'] = 'Rent a truck',
    ['return_truck'] = 'Return the truck',
    ['no_job_to_stop'] = 'You do not have an active job to stop.',
    ['job_stopped'] = 'You have stopped the active job',
    ['no_rented_vehicle_found'] = 'Could not find your rented truck nearby, make sure this was your last used vehicle.',
    ['deposit_returned'] = string.format('You have received your deposit of ~b~€%s~s~ back for returning the truck.', Config.Truck.Deposit),
    ['deposit_returned_failed'] = 'Failed to return the deposit, your vehicle is missing.',
    ['spawn_not_clear'] = 'The indicated position has to be clear of all vehicles.',
    ['not_enough_money'] = 'You do not have enough money to rent a truck.',
    ['payed_deposit'] = string.format('You have payed a deposit of ~b~€%s~s~ to rent a truck.', Config.Truck.Deposit),
    ['job_start'] = 'The job has started, you can rent a truck if you dont have one.',
    ['delivery_start'] = 'Pickup the cargo at the indicated location.',
    ['cargo_spawned'] = 'Attach the cargo and deliver it to the indicated location.',
    ['delivery_completed'] = 'The delivery has been completed.',
    ['cargo_pickup_blip_label'] = 'Cargo pickup',
    ['cargo_delivery_blip_label'] = 'Cargo delivery',
    ['target_spawn_trailer'] = 'Get cargo',
    ['cargo_delivery_instruction'] = 'Hold [H] to detach the cargo.',
    ['all_delivery_completed'] = 'You have completed all the deliveries.',
    ['all_delivery_completed_return_truck'] = 'You have completed all the deliveries, return your truck to receive your deposit back.',
    ['reward_received'] = string.format('You have received a reward of ~b~€%s~s~.', Config.Reward),
    ['rent_truck_cooldown'] = 'You must wait before renting another truck.'
}

-- Set to true to enable debug features, debug-mode enables the use of the command /cargobox, this will display a box in front of the player to help with the cargo positioning
-- Use the mouse to move the cargobox, the scrollwheel to rotate the cargobox and right-mouse-click to copy the entry for Config.Coords.Cargo, and left-mouse-click to copy the entry for Config.Coords.CargoDelivery
-- You can stop the cargobox from displaying by using either BACKSPACE or the /cargobox command again
Config.Debug = false

Accessible Client Bridge Functions
local ESX = nil
local QBCore = nil

-- Select the correct framework
if (GetResourceState('es_extended') == 'started') then
    ESX = exports['es_extended']:getSharedObject()
elseif (GetResourceState('qb-core') == 'started') then
    QBCore = exports['qb-core']:GetCoreObject()
end

Functions = {}

-- A general function notifying the player
Functions.Notify = function(message, time)
    if (message == nil or message == '') then return end
    if time == nil then time = 5000 end

    if (ESX ~= nil) then
        ESX.ShowNotification(message, 'info', time)
        return
    elseif (QBCore ~= nil) then
        QBCore.Functions.Notify(message, 'primary', time)
        return
    end
end

-- A function to check if the player can interact with the ped
Functions.CanInteract = function()
    local playerPed = PlayerPedId()

    if IsPedDeadOrDying(playerPed, true) then
        return false
    end

    if IsPedInAnyVehicle(playerPed, false) then
        return false
    end

    return true
end

-- A function that is triggered right after a rented-truck is spawned
Functions.OnSpawnTruck = function(vehicle)
    SetVehRadioStation(vehicle, "OFF")
    DoScreenFadeOut(500)
    Wait(750)
    TaskWarpPedIntoVehicle(PlayerPedId(), vehicle, -1)
    DoScreenFadeIn(500)
    Wait(500)
end

-- A function that creates the target options to the starting ped
Functions.AddTargetOptionsToStartingPed = function(ped)
    -- For the people ussing ox-target
    if (GetResourceState('ox_target') == 'started') then
        exports.ox_target:addLocalEntity(ped, {
            {
                icon = 'fas fa-truck-fast',
                label = Config.Locales['start_job_text'],
                distance = 1.5,
                onSelect = function()
                    OnStartPedInteraction(ped)
                end,
                canInteract = function()
                    return (Functions.CanInteract() and jobData == nil)
                end
            },
            {
                icon = 'fas fa-hand',
                label = Config.Locales['stop_job_text'],
                distance = 1.5,
                onSelect = function()
                    OnStopPedInteraction(ped)
                end,
                canInteract = function()
                    return (Functions.CanInteract() and jobData ~= nil)
                end
            },
            {
                icon = 'fas fa-money-bill-transfer',
                label = Config.Locales['rent_truck'],
                distance = 1.5,
                onSelect = function()
                    OnRentTruck(ped)
                end,
                canInteract = function()
                    return (Functions.CanInteract() and Config.Truck.Enable)
                end
            },
            {
                icon = 'fas fa-rotate-left',
                label = Config.Locales['return_truck'],
                distance = 1.5,
                onSelect = function()
                    OnReturnTruck(ped)
                end,
                canInteract = function()
                    return (Functions.CanInteract() and Config.Truck.Enable)
                end
            },
        })
        return
    end

    -- For the people ussing qb-target
    if (GetResourceState('qb-target') == 'started') then
        exports['qb-target']:AddTargetEntity(ped, {
            options = {
                {
                    icon = 'fas fa-truck-fast',
                    label = Config.Locales['start_job_text'],
                    action = function()
                        OnStartPedInteraction(ped)
                    end,
                    canInteract = function()
                        return (Functions.CanInteract() and jobData == nil)
                    end
                },
                {
                    icon = 'fas fa-hand',
                    label = Config.Locales['stop_job_text'],
                    action = function()
                        OnStopPedInteraction(ped)
                    end,
                    canInteract = function()
                        return (Functions.CanInteract() and jobData ~= nil)
                    end
                },
                {
                    icon = 'fas fa-money-bill-transfer',
                    label = Config.Locales['rent_truck'],
                    action = function()
                        OnRentTruck(ped)
                    end,
                    canInteract = function()
                        return (Functions.CanInteract() and Config.Truck.Enable)
                    end
                },
                {
                    icon = 'fas fa-rotate-left',
                    label = Config.Locales['return_truck'],
                    action = function()
                        OnReturnTruck(ped)
                    end,
                    canInteract = function()
                        return (Functions.CanInteract() and Config.Truck.Enable)
                    end
                },
            },
            distance = 1.5
        })
        return
    end

    -- If you are using a different target system, you can add it here. Alternatively, if you dont have any target-script, default DrawText will be used to display the interactions.
    StartDrawTextThread(ped)
end

-- A function that creates the target options to the ped that has the cargo
Functions.AddTargetOptionsToCargoPed = function(ped, CargoData)
    -- For the people ussing ox-target
    if (GetResourceState('ox_target') == 'started') then
        exports.ox_target:addLocalEntity(ped, {
            {
                icon = 'fas fa-trailer',
                label = Config.Locales['target_spawn_trailer'],
                distance = 1.5,
                onSelect = function()
                    OnCargoPedInteraction(ped, CargoData)
                end,
                canInteract = function()
                    return (Functions.CanInteract() and IsEntityAMissionEntity(ped))
                end
            },
        })
        return
    end

    -- For the people ussing qb-target
    if (GetResourceState('qb-target') == 'started') then
        exports['qb-target']:AddTargetEntity(ped, {
            options = {
                {
                    icon = 'fas fa-trailer',
                    label = Config.Locales['target_spawn_trailer'],
                    action = function()
                        OnCargoPedInteraction(ped, CargoData)
                    end,
                    canInteract = function()
                        return (Functions.CanInteract() and IsEntityAMissionEntity(ped))
                    end
                },
            },
            distance = 1.5
        })
        return
    end

    -- If you are using a different target system, you can add it here. Alternatively, if you dont have any target-script, default DrawText will be used to display the interactions.
    CargoDrawTextThread(ped, CargoData)
end

Accessible Server Bridge Functions
local ESX = nil
local QBCore = nil

-- Select the correct framework
if (GetResourceState('es_extended') == 'started') then
    ESX = exports['es_extended']:getSharedObject()
elseif (GetResourceState('qb-core') == 'started') then
    QBCore = exports['qb-core']:GetCoreObject()
end

Functions = {}

-- This function should return true if the payment was successfull
Functions.PayDeposit = function(playerId, amount)
    if (ESX ~= nil) then
        local xPlayer = ESX.GetPlayerFromId(playerId)
        if (xPlayer.getAccount('bank').money < amount) then
            return false
        end

        xPlayer.removeAccountMoney('bank', amount)
        return true
    end

    if (QBCore ~= nil) then
        local Player = QBCore.Functions.GetPlayer(playerId)
        if (Player.PlayerData.money.bank < amount) then
            return false
        end

        Player.Functions.RemoveMoney('bank', amount)
        return true
    end

    -- No framework found, so we assume the payment was successfull
    return true
end

-- This function adds money to the player
Functions.AddMoney = function(playerId, amount)
    if (ESX ~= nil) then
        local xPlayer = ESX.GetPlayerFromId(playerId)
        xPlayer.addAccountMoney('bank', amount)
    end

    if (QBCore ~= nil) then
        local Player = QBCore.Functions.GetPlayer(playerId)
        Player.Functions.AddMoney('bank', amount)
    end
end

Functions.OnJobStart = function(playerId)
    -- The job is started
end

Functions.OnJobEnd = function(playerId, reason)
    if (reason == 'canceled') then
        -- The job is canceled
    elseif (reason == 'completed') then
        -- The job is completed
    end
end

Functions.LogSuspiciousActivity = function(playerId, reason)
    -- If a player is doing something suspicious, it is printed by this function, for instance when injecting events, usefull for anti-cheat detection
    -- print('gs_truckerjob: Player ' .. playerId .. ' shows suspicious activity: ' .. reason)
end

Code is accessible No, but core functions are accessible
Subscription-based No
Lines (approximately) 1291
Requirements None, can be run as standalone
Support Yes
2 Likes

Congratulations, it’s very successful. Users can also benefit from the free truckerjob we have done in the past if they wish.