BUTY SHOP
WebDiscord
  • πŸ’œBUTY DOCUMENTATION
  • ⚠️INFORMATION
    • LICENSES
    • OUR TERMS
    • SUPPORT
  • πŸ“šGUIDES
    • ⭐Infinite JOBS
      • INSTALLATION
      • HOW TO DO
    • 🌿Gardener Job
      • INSTALLATION
    • ❗Infinite Activities
      • INSTALLATION
    • πŸ›©οΈFlight School
      • INSTALLATION
    • 🚀Boat School
      • INSTALLATION
    • πŸ’³License System
      • INSTALLATION
      • EXPORT INTEGRATION
      • COMMANDS
    • πŸš—Vehicle Shop
      • INSTALLATION
    • ⛏️Advanced Miner
      • INSTALLATION
    • πŸ”„Progress Bar
      • INSTALLATION
    • πŸ’ŠAdvanced Sell Drugs
      • INSTALLATION
      • COMMON PROBLEMS
    • 🌊Rent Water Activities
      • INSTALLATION
    • 🏎️Rent Kart Vehicles
      • INSTALLATION
    • πŸ§‘β€πŸ¦±Advanced Identity
      • INSTALLATION
    • 🚚Advanced Trucker
      • INSTALLATION
    • πŸ›©οΈAdvanced Airplane
      • INSTALLATION
    • 🚌Advanced Bus
      • INSTALLATION
    • ♻️Advanced Garbage
      • INSTALLATION
      • COMMON PROBLEMS
  • βš™οΈCOMMON ERRORS
Powered by GitBook
On this page
  • 1. DOWNLOAD
  • 2. DEPENDENCIES AND INSTALLATION
  • 3. CONFIG
  • 4. CHANGING THE AESTHETICS
  1. GUIDES
  2. Infinite JOBS

INSTALLATION

Read very well and follow all the steps below. If you find any error or have any doubt open a ticket.

PreviousInfinite JOBSNextHOW TO DO

Last updated 3 months ago

1. DOWNLOAD

The first step is to download the product we have just purchased. To do this we will go to our account and search for "Buty-InfiniteJobs".

2. DEPENDENCIES AND INSTALLATION

To install it add the resource to your scripts folder and put the following in your SERVER.CFG:

ensure Buty-InfiniteJobs-Props
ensure Buty-InfiniteJobs

There are 1 dependencie:

We also recommend our beautifully designed Advanced Progress Bar with lots of functions. This one has a very low price and fits very well with the aesthetics of any server:

You can add it to Infinite Jobs, adding the export in the config_function.lua. If you open ticket in discord, we will be happy to help.

3. CONFIG

The following will explain all the settings, one of the most important things that I recommend you spend a few minutes to understand in order to offer your users the best possible experience.

This script comes with 25 jobs already preconfigured and activated, you only have to ensured the script (and dependencies) and they will be ready.

Even so, check the CONFIG of the jobs and configure the uniforms, salaries and vehicles to your liking.

The economy of the jobs is not configured, so we recommend that you review it and adapt it to each person's tastes.

Here you will only have to configure your framework, your database and the location of the Job Center.

In addition to some extra settings, such as the type of gender that your server uses.

In UseKeys, UseFuel, UseDeleteVehicle you activate it in case you have filled some of the integrations in config_functions.


Configuration = {
    Framework = esxHas and 'esx' or qbHas and 'qb' or 'esx',
    Mysql = 'oxmysql', -- Database type: 'oxmysql', 'mysql-async', or 'ghmattisql'
    UseTarget = false, -- -- Activate it if you want to use target. Set to false if you want floating text
    Language = 'en', -- 'en' or 'es' by default (you can create more)
    JobForID = false, -- Do you want the jobs to be by database, i.e police?
    UseClothes = true, -- Do you want users to have to dress?
    EquipToolAutomatically = false, -- If true,the tool will automatically equip when you need it, if false, you will have to use the key to equip it when you need it
    toolbelt = false, -- If true, then the tool will be visible on your belt when you unequip it, if false it will be invisible on your belt
    RequireJobFromAllGroup = true, -- If true, all group members must have the job; if false, only the leader needs the job (this will only work if JobForID = true)
    Limit_work = {use=false, totalwork=2 , WorkTime=10},
    ZoomandCameras = true, -- disable cameras and zooms
    Color_UI = "#9B37FF", -- Change UI color
    Color_Marker = {106, 3, 247}, -- change marker color (RGB)
    Maxlevel = 10, -- maximum number of levels they can reach
    ControlKey_TakeObj = 73, -- Change the key with which objects in the trunk are grabbed to process (Default: X)
    split_lobby_payment = false, -- true: the payment will be divided among the players on the team, false: it will pay all players in the lobby the entire amount.
} 

JobCenter = { -- Here you can add more job centers
    {
        coord = vec4(-534.1885, -211.6769, 37.6498, 109.6640), 
        model = "cs_barry",
        jobs = {}, -- If you want you can add different jobs to each one
    },
     {
        coord = vec4(-534.1885, -211.6769, 37.6498, 109.6640), 
        model = "cs_barry",
        jobs = {"miner","plumber"}, -- For example, here only job 1 and 2 would appear.
    },
}

Config_Sell = { --new wholesale and retail system

    activate = false, -- activated

    CreateNPC = { -- random coordinates where it will appear
        {model = "cs_joeminuteman", coord = vec4(1549.2064, 2193.1531, 78.8437, 60.7733)},
        {model = "cs_joeminuteman", coord = vec4(1546.3419, 2199.2021, 78.7436, 17.6115)},
        {model = "cs_joeminuteman", coord = vec4(1542.6492, 2193.8923, 78.8395, 141.4520)},
        {model = "cs_joeminuteman", coord = vec4(1556.7509, 2198.4910, 78.9155, 272.3318)},
    },

    wholesale = 1500, -- Minimum amount you must have to sell
    retail = 5, -- Minimum amount you must have to sell

    paymentmethod = {
        option = "cash", -- cash/bank/item
        item_name = "" -- if you use <option = "item"> then put here the name of the item you will pay with.
    },

    items = {
        { 
            img = "./img/item.png", 
            name = "meth", 
            label = "wood", 
            price = {
                wholesale = {min = 1, max = 10}, -- price min and max
                retail = {min = 1, max = 60}, -- price min and max
            } 
        },
        { 
            img = "./img/item.png", 
            name = "meth",
            label = "Stone", 
            price = {
                wholesale = {min = 1, max = 10}, -- price min and max
                retail = {min = 1, max = 60}, -- price min and max
            } 
        },
    }
}

Here you can customize the pre-created jobs or create your own jobs.

JobInfo

  • Name: name of the job that appears in the job center.

  • JobID: If you use JobForID in the configuration, then here you will need to add the name of the job in your database.

  • ExperienceRequired: every how many xp you level up.

  • info: description that appears in the work center.

  • Tutorial: add tutorial steps.

JobConfig

Tool = {
            prop = "w_me_hatchet", --prop model name
            objcoord = {28422,0.05, 0.04, 0.0, 280.0, 740.0, 330.0}, -- prop coord in hand
            objcoordbelt = {11816, 0.34, 0.0, -0.28, 80.0, -80.0, -10.0}, -- coordinates where the prop will be saved, for example now it is at the waist
            animation_action = {"melee@large_wpn@streamed_core","ground_attack_on_spot_body",8000}, --anim and time
            animation_take = nil, -- anim take prop
            particles = "ent_dst_wood_splinter" -- --particles at the end of the task
        },

        type = 2,

        {
            CreateGroup = vec4(-559.7979, 5356.7124, 69.2145, 78.3917),

            CreateGroupPed_model = "a_m_m_farmer_01",

            Workclothes = vec4(-571.1516, 5361.1753, 69.2145, 81.0137),

            Vehicle = {
                coord = vec4(-579.8630, 5369.0811, 69.3189, 162.3172),
                spawnvehicle = vec4(-576.1255, 5374.6016, 70.2464, 299.7000),
                model = "bison",
                doors = {5},
                coord_prop_tool = {
                    [1] = {-0.63, -1.03, 0.54, 90.0, 0.0, 0.0},
                    [2] = {-0.53, -1.13, 0.54, -90.0, -170.0, 0.0},
                    [3] = {0.63, -1.13, 0.59, -90.0, -170.0, 0.0},
                    [4] = {0.53, -1.03, 0.59, 90.0, 0.0, 0.0},
                },
                coord_prop_vehicle = { -- coordinates where the props will appear when loaded into your vehicle
                    [1] = {-0.21, -1.0, 0.45, 0.90, 0.0, 0.0},
                    [2] = {0.26, -1.0, 0.45, 0.90, 0.0, 0.0}, 
                    [3] = {-0.48, -1.65, 0.45, 0.90, 0.0, 0.0}, 
                    [4] = {0.0, -1.65, 0.45, 0.90, 0.0, 0.0},
                    [5] = {0.48, -1.65, 0.45, 0.90, 0.0, 0.0},
                    [6] = {0.48, -2.15, 0.45, 0.90, 0.0, 0.0}, 
                    [7] = {0.0, -2.15, 0.45, 0.90, 0.0, 0.0}, 
                    [8] = {-0.48, -2.15, 0.45, 0.90, 0.0, 0.0},
                    [9] = {-0.21, -1.0, 0.91, 0.90, 0.0, 0.0}, 
                    [10] = {0.26, -1.0, 0.91, 0.90, 0.0, 0.0}, 
                    [11] = {-0.48, -1.65, 0.91, 0.90, 0.0, 0.0}, 
                    [12] = {0.0, -1.65, 0.91, 0.90, 0.0, 0.0}, 
                    [13] = {0.48, -1.65, 0.91, 0.90, 0.0, 0.0}, 
                    [14] = {0.48, -2.15, 0.91, 0.90, 0.0, 0.0}, 
                    [15] = {0.0, -2.15, 0.91, 0.90, 0.0, 0.0}, 
                    [16] = {-0.48, -2.15, 0.91, 0.90, 0.0, 0.0}, 
                }
            },

            CollectedProp = {
                name = "prop_chopblock_fury", -- name of the prop that appears when finishing a task, which you must load into the vehicle
                animAttachHands = {"anim@heists@box_carry@", "idle"}, animation that does when grabbing the object
                attachcoordHands = {28422, 0.0, -0.08, 0.04, 0.0, -90.0, 0.0}, -- coord of the object in your hands with the animation
                attachcoordProcess = {0.0, -1.8, 1.10, 0.0, 0.0, 0.0} -- coordinates where the prop is placed on the processing tape
            },

            Route = {
                [1] = {   
                    
                    {
                        coord = vec4(-622.9656, 5500.0391, 51.3581, 154.9108),                                                       
                        propname = "prop_log_01",                    
                        GetItem = {use = false, name = "wood", quantity = 1},                           
                    },
                
                    {
                        coord = vec4(-618.0844, 5501.2227, 51.1275, 306.3838),                                                       
                        propname = "prop_log_01",                     
                        GetItem = {use = false, name = "wood", quantity = 1},                             
                    },
                
                },
                
                [2] = {   
                    
                    {
                        coord = vec4(-429.7848, 5114.0317, 129.1521, 108.7410),                                                       
                        propname = "prop_log_01",                    
                        GetItem = {use = false, name = "wood", quantity = 1},                           
                    },
                
                    {
                        coord = vec4(-436.6448, 5099.8628, 133.8579, 282.1778),                                                       
                        propname = "prop_log_01",                     
                        GetItem = {use = false, name = "wood", quantity = 1},                             
                    },
                
               
                },
                
            },

            ProcessCoord = vec4(-553.8823, 5286.6250, 73.5063, 68.0243), -- process prop coord

            Finish = {
                model = "cs_joeminuteman", 
                coord = vec4(-567.6278, 5253.1714, 69.4874, 72.5164), 
                Quantity = 1000, 
                paymentmethod = {
                    option = "cash", -- cash/bank/item
                    item_name = "" -- if you use <option = "item"> then put here the name of the item you will pay with.
                },
                exp = 50, 
                increase_per_level = 100
            },
        },

Here you can customize the pre-created jobs or create your own jobs.

JobInfo

  • Name: name of the job that appears in the job center.

  • JobID: If you use JobForID in the configuration, then here you must add the name of the job in your database.

  • ExperienceRequired: every how many xp you level up.

  • info: description that appears in the work center.

  • Tutorial: Add the tutorial steps.

JobConfig

Tool = {
    prop = "prop_cs_trowel", -- prop model
    objcoord = {28422,0.08, 0.05, 0.0, 120.0, -10.0, -50.0}, -- coord of the prop in the hand
    objcoord2 = {28422,0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, -- strut coord in hand while doing animation
    animation_action = {"amb@world_human_gardener_plant@female@base", "base_female",3000}, -- anim and time anim
    animation_take = nil, -- anim take tool
    particles = "ent_anim_snot_blow", --particles at the end of the task
},

 type = 1, There is type 1 and type 2, type 1 is the classic and type 2 is the advanced

    deleteprop = true, -- Do you need the prop to be removed upon completion of the task?

{
     CreateGroup = vec4(-1753.2039, -724.2020, 9.4052, 142.5494), -- coord create group

     CreateGroupPed_model = "cs_omega", -- model npc create group

     Workclothes = vec4(-1747.3628, -726.1576, 9.4234, 44.8436), -- coord workclothes

     Vehicle = {
          coord = vec4(-1728.5122, -713.1675, 9.1175, 325.0412), -- coord prop take vehicle
          spawnvehicle = vec4(-1732.3912, -722.1490, 10.3381, 253.9162), -- coord spawn vehicle
          doors = {2,3}, -- number of trunk doors
          model = "burrito", -- model vehicle
          coord_prop_tool = { -- coord where the tools will be placed in the vehicle
          [1] = { -0.6, -0.26, -0.1, 0.0, 0.0, 0.0},
          [2] = {-0.2, -0.26, -0.1, 0.0, 0.0, 0.0},
          [3] = {0.3, -0.26, -0.1, 0.0, 0.0, 0.0},
          [4] = {0.1, -0.26, -0.1, 0.0, 0.0, 0.0},
     }, 
  },

  skill = { -- skill system
      use = true,
      difficultyLevels = { 'easy', 'easy', {areaSize = 60, speedMultiplier = 1.1}, 'easy' },
      controls = {'w', 'a', 's', 'd'},
      particles = "",
 },  

Route = { Here are the routes, you can add as many as you want and they will be random
                
     [1] = {
{
         coord = vec4(-1899.8516, 219.1252, 84.2944, 11.3411),
         propname = "prop_veg_crop_04_leaf",
         GetItem = { use = false, name = "gardener", quantity = 1},
},
{
        coord = vec4(1386.2991, -590.7735, 74.4707, 221.0031),
        propname = "prop_veg_crop_04_leaf",
        GetItem = { use = false, name = "gardener", quantity = 1},
},
                    
}, 
    [2] = {
{
        coord = vec4(1386.2991, -590.7735, 74.4707, 221.0031),
        propname = "prop_veg_crop_04_leaf",
        GetItem = { use = false, name = "gardener", quantity = 1},
},
{
        coord = vec4(1386.2991, -590.7735, 74.4707, 221.0031),
        propname = "prop_veg_crop_04_leaf",
        GetItem = { use = false, name = "gardener", quantity = 1},
},
                    
}
},

 Finish = {
         model = "s_m_m_cntrybar_01", -- model npc finish
         coord = vec4(-1722.3198, -736.2484, 9.2014, 48.6792), -- coord spawn npc
         Quantity = 1000, -- amount he pays you
         paymentmethod = {
            option = "cash", -- cash/bank/item
            item_name = "" -- if you use <option = "item"> then put here the name of the item you will pay with.
},
          exp = 50, 
          increase_per_level = 100 -- amount that increases per level
  },
},

    { 
        [1] = {jobs = "Lumberjack", img = "./img/lumberjack.png",img2 =  "./img/lumberjack2.png", info = "Help is needed with tree cutting, just cut some trees and we will pay you for it."},
        
        [2] = {
            [1] = {Workclothes = {{x = -552.8, y = 5348.68, z = 74.76, h = 61.92}, nameblip = "~h~[JOB]~h~ Work clothes"}},
            
            [2] = {payout = {{x = -566.12, y = 5326.12, z = 72.6, h = 67.28}, pedmodel = "s_m_m_cntrybar_01", pedanim = "WORLD_HUMAN_SMOKING", nameblip = "~h~[JOB]~h~ Work Payout"}},

            [3] = {coordsjob = {
                prop = false,
                propname = "prop_tree_olive_creator",
                nameblip = "Tree",
                text = "Press ~h~[E]~h~",
                { x = -554.64, y = 5511.76, z = 59.28, objZ= 2 , take = false}, 
                { x = -565.36, y = 5502.84, z = 57.04, objZ= 2 , take = false}, 
                
                { x = -553.12, y = 5541.24, z = 60.12, objZ= 2 , take = false}, {x = -524.16, y = 5561.68, z = 66.28, objZ= 2 , take = false},

                { x = -533.56, y = 5536.56, z = 64.4, objZ= 2 , take = false}, { x = -536.92, y = 5555.28, z = 61.48, objZ= 2 , take = false}, {x = -523.48, y = 5569.08, z = 66.04, objZ= 2 , take = false},

                { x = -506.56, y = 5564.44, z = 70.52, objZ= 2 , take = false}, { x = -575.64, y = 5526.6, z = 53.04, objZ= 2 , take = false}, {x = -588.48, y = 5496.16, z = 54.16, objZ= 2 , take = false},
            }},

            [4] = { 
                [1] = {getvehicle = {{x = -573.8, y = 5369.64, z = 69.24, h = 256.68}, pedmodel = "a_m_m_farmer_01", pedanim = "WORLD_HUMAN_AA_COFFEE", nameblip = "~h~[JOB]~h~ Work vehicle"}}, 
                [2] = {spawnvehicle = {x = -562.64, y = 5370.08, z = 70.2, h = 346.56}}, 
                [3] = {vehiclename = "rebel"},
                [4] = {vehicle = true}
            }
        },

        [3] = {
            [1] = {anim = "melee@hatchet@streamed_core", anim2 = "plyr_front_takedown"},
            [2] = {obj = true, nameobj = "w_me_hatchet", objX = 0.09, objY = 0.01, objZ = 0.0, objrotX = 300.0, objrotY = 720.0,objrotZ = 330.0},
            [3] = {animtime = 5000}
        
        },

        [4] = {
            [1] = {
                Pay_Advanced = false,

                Pay = 1550, IncreasePerLVL = 1,

                PayPerLVL = {
                    [0] = 100,
                    [1] = 101,
                    [2] = 102,
                    [3] = 103,
                    [4] = 104,
                    [5] = 105,
                    [6] = 106,
                    [7] = 107,
                    [8] = 108,
                    [9] = 109,
                    [10] = 110,
                },
            
            },
            [2] = {EXP = 50, IncreasePerLVL = 1},
            [3] = {GetItem = false, ItemName = "water", Amount = 1}
        },
        
        [5] = {
            ['clothes'] = {
                male = {

                    tshirt_1 = 15,  tshirt_2 = 0,
                    torso_1 = 234,   torso_2 = 19,
                    decals_1 = 0,   decals_2 = 0,
                    arms = 37,
                    pants_1 = 9,   pants_2 = 7,
                    shoes_1 = 12,   shoes_2 = 0,
                    chain_1 = 0,    chain_2 = 0,
                    helmet_1 = 5,  helmet_2 = 0,
                    ears_1 = -1,     ears_2 = 0,
                    bproof_1 = 0,  bproof_2 = 0
                },
                female = {
                    tshirt_1 = 201,  tshirt_2 = 1,
                    torso_1 = 167,   torso_2 = 0,
                    decals_1 = 0,   decals_2 = 0,
                    arms = 44,
                    pants_1 = 60,   pants_2 = 0,
                    shoes_1 = 52,   shoes_2 = 0,
                    chain_1 = -1,    chain_2 = 0,
                    helmet_1 = -1,  helmet_2 = 0,
                    bproof_1 = 0,  bproof_2 = 0
                }
            },         
        },

    },

Here are the important functions open. You will be able to set your Key System, Gasoline System, set up your notification system...


if Configuration.Framework ~= 'esx' then
    return
end

ESX = exports['es_extended']:getSharedObject()

playerJob = nil
playerJobName = nil
taskblip = {}
task_blip = {}

if Configuration.JobForID then
    Citizen.CreateThread(function()

        while ESX == nil do
            Citizen.Wait(100)
        end
        
        while playerJob == nil do
            playerJob = ESX.GetPlayerData().job
            Wait(1000)
        end

        StartWithJob()
    end)
end

RegisterNetEvent('esx:setJob', function(job, lastJob)
    playerJob = job
end)

hintToDisplay = function(text, coords)
    local playerCoords = GetEntityCoords(PlayerPedId())
    local dist = #(vector3(coords.x, coords.y, coords.z) - playerCoords)

    if dist < 1.5 then
        DrawText3Ds(coords.x, coords.y, coords.z, text, 0.35)
    else
        DrawText3Ds(coords.x, coords.y, coords.z, text, 0.35)
    end
end

function DrawText3Ds(x, y, z, text, scale)
    SetTextScale(scale or 0.35, scale or 0.35)
    SetTextFont(4)
    SetTextProportional(1)
	SetTextColour(255, 255, 255, 215)
    SetTextEntry("STRING")
    SetTextCentre(true)
    AddTextComponentString(text)
    SetDrawOrigin(x, y, z, 0)

    DrawText(0.0, 0.0)

    local textLength = string.len(text)
    local factor = textLength / 370
    DrawRect(0.0, 0.0125, 0.015 + factor, 0.03, 0, 0, 0, 100)

    ClearDrawOrigin()
end

Notify = function(type, text, time)
    -- time = 10000
    -- if type == 'success' then
    --     exports["Venice-Notification"]:Notify(text, time, "check", options)
    -- elseif type == 'error' then
    --     exports["Venice-Notification"]:Notify(text, time, "error", options)
    -- elseif type == 'info' then
    --     exports["Venice-Notification"]:Notify(text, time, "info", options)
    -- end

    ESX.ShowNotification(text)
end

GetJob = function(player)
    local job = lib.callback.await('Buty-InfiniteJobs:server:GetJob', false, player)
    return job
end

setblip = function(name,coords,text,number_blip)
    if name == "jobcenter" then
        jobcenter_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(jobcenter_blip, 162)
        SetBlipColour(jobcenter_blip, 27)
        SetBlipScale(jobcenter_blip, 0.9)
        SetBlipAsShortRange(jobcenter_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(jobcenter_blip)
    elseif name == "menu_group" then
        menu_group_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(menu_group_blip, 516)
        SetBlipColour(menu_group_blip, 27)
        SetBlipScale(menu_group_blip, 0.4)
        SetBlipAsShortRange(menu_group_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(menu_group_blip)
    elseif name == "workclothes" then
        workclothes_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(workclothes_blip, 366)
        SetBlipColour(workclothes_blip, 27)
        SetBlipScale(workclothes_blip, 0.4)
        SetBlipAsShortRange(workclothes_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(workclothes_blip)
    elseif name == "VehicleBlip" then
        vehicle_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(vehicle_blip, 641)
        SetBlipColour(vehicle_blip, 27)
        SetBlipScale(vehicle_blip, 0.4)
        SetBlipAsShortRange(vehicle_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(vehicle_blip)
    elseif name == "task" then
        task_blip[number_blip] = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(task_blip[number_blip], 271)
        SetBlipColour(task_blip[number_blip], 27)
        SetBlipScale(task_blip[number_blip], 0.4)
        SetBlipAsShortRange(task_blip[number_blip], true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(task_blip[number_blip])
        -- table.insert(taskblip, task_blip[number_blip])
    elseif name == "process" then
        process_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(process_blip, 267)
        SetBlipColour(process_blip, 27)
        SetBlipScale(process_blip, 0.4)
        SetBlipAsShortRange(process_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(process_blip)
    elseif name == "pay" then
        pay_blip = AddBlipForCoord(coords[1], coords[2], coords[3])
        SetBlipSprite(pay_blip, 207)
        SetBlipColour(pay_blip, 27)
        SetBlipScale(pay_blip, 0.4)
        SetBlipAsShortRange(pay_blip, true)
        BeginTextCommandSetBlipName("STRING")
        AddTextComponentSubstringPlayerName(text)
        EndTextCommandSetBlipName(pay_blip)
        SetNewWaypoint(coords[1], coords[2])
    end
end

progress = function()
    local useButyProgress = GetResourceState('Buty-Progress') == 'started'
    if useButyProgress then
        exports["Buty-Progress"]:on({
            time = 3000, 
            text = _U('JOBS_NOTIFICATION_PROGRESS'), 
            color = "linear-gradient(20.5deg, #AC41DE 9.83%, rgba(172, 65, 222, 0) 93.95%)",
            color2 = "#AC41DE",
        })
    else
        lib.progressBar({
            duration = 3000,
            label = _U('JOBS_NOTIFICATION_PROGRESS'),
            useWhileDead = false,
            canCancel = true,
            disable = {
                car = true,
            },
        })
    end
end

spawnvehicle = function(vehicle)
    local plate = GetVehicleNumberPlateText(vehicle)
    local model = GetEntityModel(vehicle)

    -- Verificar quΓ© sistema de llaves estΓ‘ activo
    local useJaksamsKey = GetResourceState('vehicles_keys') == 'started'
    local useWasabiKey = GetResourceState('wasabi_carlock') == 'started'
    local useQuasarKeys = GetResourceState('qs-vehiclekeys') == 'started'
    local useAK47Keys = GetResourceState('ak47_vehiclekeys') == 'started'
    local useQBKeys = GetResourceState('qb-vehiclekeys') == 'started'
    local useMKKeys = GetResourceState('mk_vehiclekeys') == 'started'
    local useDusaKeys = GetResourceState('dusa_vehiclekeys') == 'started'
    local useMRNewbKeys = GetResourceState('mrnewb_vehiclekeys') == 'started'

    -- Asignar llaves segΓΊn el sistema detectado
    if useJaksamsKey then
        TriggerServerEvent("vehicles_keys:selfGiveVehicleKeys", plate)
    elseif useWasabiKey then
        exports.wasabi_carlock:GiveKey(plate)
    elseif useQuasarKeys then
        exports['qs-vehiclekeys']:GiveKeys(plate, model, true)
    elseif useAK47Keys then
        exports['ak47_vehiclekeys']:GiveVirtualKey(plate)
    elseif useQBKeys then
        TriggerEvent("qb-vehiclekeys:client:SetOwner", plate)
        TriggerEvent("qb-vehiclekeys:client:AddKeys", plate)
    elseif useMKKeys then
        exports["mk_vehiclekeys"]:AddKey(vehicle)
    elseif useDusaKeys then
        exports['dusa_vehiclekeys']:IntegrateKey(plate)
    elseif useMRNewbKeys then
        exports.MrNewbVehicleKeys:GiveKeys(vehicle)
    end

    -- Configurar combustible a 100%
    SetVehicleFuelLevel(vehicle, 100.0)
end

Removevehicle = function(vehicle)
    local plate = GetVehicleNumberPlateText(vehicle)
    local model = GetEntityModel(vehicle)

    -- Verificar quΓ© sistema de llaves estΓ‘ activo
    local useWasabiKey = GetResourceState('wasabi_carlock') == 'started'
    local useQuasarKeys = GetResourceState('qs-vehiclekeys') == 'started'
    local useJaksamsKey = GetResourceState('vehicles_keys') == 'started'
    local useAK47Keys = GetResourceState('ak47_vehiclekeys') == 'started'
    local useQBKeys = GetResourceState('qb-vehiclekeys') == 'started'
    local useMKKeys = GetResourceState('mk_vehiclekeys') == 'started'
    local useDusaKeys = GetResourceState('dusa_vehiclekeys') == 'started'
    local useMRNewbKeys = GetResourceState('mrnewb_vehiclekeys') == 'started'

    -- Remover llaves segΓΊn el sistema detectado
    if useWasabiKey then
        exports.wasabi_carlock:RemoveKey(plate)
    elseif useQuasarKeys then
        exports['qs-vehiclekeys']:RemoveKeys(plate, model)
    elseif useJaksamsKey then
        TriggerServerEvent("vehicles_keys:selfRemoveKeys", plate)
    elseif useAK47Keys then
        exports['ak47_vehiclekeys']:RemoveVirtualKey(plate)
    elseif useMRNewbKeys then
        exports.MrNewbVehicleKeys:RemoveKeys(vehicle)
    end
end


RegisterCommand('canceljob', function(source, args, rawCommand)
    if job_incurse then canceljob() end
end, false)

CreateTarget = function(data)
    if data.targetType == 'AddBoxZone' then
        if data.distance == nil then
            distance = 3.0
        else
            distance = data.distance
        end

        exports["qtarget"]:AddBoxZone(data.identifier, data.coords, data.length, data.width, {
            name=data.identifier,
            heading=data.heading,
            debugPoly=false,
            minZ=data.coords.z-0.7,
            maxZ=data.coords.z+1.5,
        }, {
            options = data.options,
            distance = distance,
        })
    elseif data.targetType == 'entity' then
     
        if data.distance == nil then
            distance = 2.5
        else
            distance = data.distance
        end
        exports.qtarget:AddTargetEntity(data.entitys, {
            options = data.options,
            label = data.identifier,
            distance = distance
        })  
    end
end


This is the open esx file, but there is also QB

if Configuration.Framework ~= 'esx' then
    return
end

local webhook_link = "" -- webhook logs

function SendWebhookLog(message,color)
    local embed = {
        {
            ['color'] = color,
            ['title'] = "πŸ“’ INFINITE JOBS",
            ['description'] = message,
            ['footer'] = {
                ['text'] = os.date("%Y-%m-%d %H:%M:%S"),
            },
        }
    }
    PerformHttpRequest(webhook_link, function(err, text, headers) end, 'POST', json.encode({
        username = "InfiniteJobs Logs",
        embeds = embed
    }), { ['Content-Type'] = 'application/json' })
end

ESX = exports['es_extended']:getSharedObject()

function GetIdPlayer(player)
    return ESX.GetPlayerFromId(player) or ESX.GetPlayer(player)
end

function GetIdentifier(player)
    return player.identifier
end

function giveReward(player, amount, configpay, level)
    local xPlayer = GetIdPlayer(player)
    local playerName = GetPlayerName(player)
    local rewardType = configpay.paymentmethod.option
    local rewardAmount = amount + (level * configpay.increase_per_level)
    local itemName = configpay.paymentmethod.item_name

    if rewardType == 'cash' then
        xPlayer.addMoney(rewardAmount)
        sendChatMessage(player, _U('JOBS_NOTIFICATION_REWARD_MONEY') .. rewardAmount .. _U('JOBS_NOTIFICATION_REWARD_CASH'))
    elseif rewardType == 'bank' then
        xPlayer.addAccountMoney('bank', rewardAmount)
        sendChatMessage(player, _U('JOBS_NOTIFICATION_REWARD_MONEY') .. rewardAmount .. _U('JOBS_NOTIFICATION_REWARD_BANK'))
    elseif rewardType == 'item' then
        if itemName then
            xPlayer.addInventoryItem(itemName, rewardAmount)
            sendChatMessage(player, _U('JOBS_NOTIFICATION_REWARD_ITEM') .. rewardAmount .. "x " .. itemName .. ".")
        else
            print("Item name no especificado.")
        end
    else
        print("Tipo de recompensa no vΓ‘lido.")
    end
end

function giveitem(player,itemname,quantity)
    local xPlayer = GetIdPlayer(player)
    xPlayer.addInventoryItem(itemname, quantity)
    sendChatMessage(player, _U('JOBS_NOTIFICATION_GET') .. quantity .. "x " .. itemname .. ".")
end

function sendChatMessage(player, message)
    TriggerClientEvent('chat:addMessage', player, {
        args = { "SYSTEM", message }
    })
end

RegisterNetEvent("Buty-InfiniteJobs:setJob")
AddEventHandler("Buty-InfiniteJobs:setJob", function(player, jobname, grade)
    local xPlayer = GetIdPlayer(source)
    xPlayer.setJob(jobname, grade)
    return
end)

lib.callback.register('Buty-InfiniteJobs:server:GetJob', function(source, player)
    local xPlayer = GetIdPlayer(player)
    local job = xPlayer.getJob()
    local jobName = job.name
    return jobName
end)

lib.callback.register('Buty-InfiniteJobs:server:GetItems', function(source, items)
    local xPlayer = ESX.GetPlayerFromId(source)
    local itemsToSend = {}

    for _, itemName in ipairs(items) do
        local item = xPlayer.getInventoryItem(itemName.name)
        
        if item and item.count > 0 then
            local itemPrice = nil
            for _, generatedItem in ipairs(Config_Sell.itemsWithPrices) do
                if generatedItem.name == itemName.name then
                    itemPrice = generatedItem.price
                    break
                end
            end
            
            if itemPrice then
                table.insert(itemsToSend, {
                    label = itemName.label,
                    name = itemName.name,
                    img = itemName.img,
                    count = item.count,
                    price = itemPrice
                })
            end
        end
    end
    
    return itemsToSend
end)

RegisterServerEvent('Buty-InfiniteJobs:server:s3ll3', function(data)
    local xPlayer = ESX.GetPlayerFromId(source)
    local item = xPlayer.getInventoryItem(data.selectedItem)
    local totalPrice = 0

    if data.selltype == "retail" then
        selltype_ = Config_Sell.retail
        totalPrice = data.priceItemRetail * selltype_
    elseif data.selltype == "wholesale" then
        selltype_ = Config_Sell.wholesale
        totalPrice = data.priceItemWholesale * selltype_
    end

    if Config_Sell.paymentmethod.option == "cash" then
        xPlayer.addMoney(totalPrice)
    elseif Config_Sell.paymentmethod.option == "bank" then
        xPlayer.addAccountMoney('bank', totalPrice)
    elseif Config_Sell.paymentmethod.option == "item" then
        xPlayer.addInventoryItem(data.selectedItem, selltype_)
    end

    xPlayer.removeInventoryItem(data.selectedItem, selltype_)
end)

4. CHANGING THE AESTHETICS

As already explained, the colour of the Interface is changed from the CONFIG.lua

But you can also change the BACKGROUND IMAGE, either by putting one of your choice or by changing the colour from one of the backgrounds we have added in the BACKGROUND folder inside the HTML folder.

For that you will have to go to line 17 of the INDEX.HTML and change the name of the image:

 <img class="background-img" src="./background/" alt="">

These are the colours in which the BACKGROUND is available. You can always add more.

πŸ“š
⭐
KEYMASTER
ox_libs
https://butycall.tebex.io/package/5384327