# INSTALLATION

## 1. **DOWNLOAD**

The first step is to download the product we have just purchased. To do this we will go to our [KEYMASTER](https://keymaster.fivem.net/asset-grants) 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**:

<pre class="language-lua"><code class="lang-lua"><strong>ensure Buty-InfiniteJobs-Props
</strong>ensure Buty-InfiniteJobs
</code></pre>

There are 1 dependencie:&#x20;

[ox\_libs](https://github.com/overextended/ox_lib)

{% hint style="info" %}
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:&#x20;

<https://butycall.tebex.io/package/5384327>

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.
{% endhint %}

## 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.

{% hint style="info" %}
This script comes with **25 jobs already preconfigured and activated**, you only have to ensured the script (and dependencies) and they will be ready.
{% endhint %}

{% hint style="info" %}
Even so, check the CONFIG of the jobs and configure the **uniforms**, **salaries** and **vehicles** to your liking.
{% endhint %}

{% hint style="info" %}
The economy of the jobs is not configured, so we recommend that you review it and adapt it to each person's tastes.
{% endhint %}

{% tabs %}
{% tab title="CONFIG" %}
{% hint style="info" %}
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.**
{% endhint %}

{% code lineNumbers="true" %}

```lua

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
            } 
        },
    }
}


```

{% endcode %}
{% endtab %}

{% tab title="JOBS ADVANCED" %}
{% hint style="info" %}
Here you can customize the pre-created jobs or create your own jobs.
{% endhint %}

**JobInfo**&#x20;

* **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
            },
        },
```

{% endtab %}

{% tab title="JOBS CLASSICS" %}
{% hint style="info" %}
Here you can customize the pre-created jobs or create your own jobs.
{% endhint %}

**JobInfo**&#x20;

* **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
  },
},

```

{% code lineNumbers="true" %}

```lua
    { 
        [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
                }
            },         
        },

    },
```

{% endcode %}
{% endtab %}

{% tab title="OPEN CLIENT" %}
{% hint style="info" %}
Here are the important functions open. You will be able to set your Key System, Gasoline System, set up your notification system...
{% endhint %}

```lua

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



```

{% endtab %}

{% tab title="OPEN SERVER" %}
{% hint style="info" %}
This is the open esx file, but there is also QB
{% endhint %}

```lua
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)
```

{% endtab %}
{% endtabs %}

## 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.

<figure><img src="https://3526868747-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeQWzokUSwvmD8VZ4PFkY%2Fuploads%2F60SCvpbti6fc8skO2fam%2FCaptura%20de%20pantalla%202023-04-17%20170902.png?alt=media&#x26;token=d5fef8a1-2642-4bde-a83c-36c8b77cca89" alt=""><figcaption></figcaption></figure>

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

<pre class="language-html"><code class="lang-html"> &#x3C;img class="background-img" src="./background/<a data-footnote-ref href="#user-content-fn-1">PURPLE.png</a>" alt="">
</code></pre>

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

<figure><img src="https://3526868747-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeQWzokUSwvmD8VZ4PFkY%2Fuploads%2F9JfskPhHkFk2Nr2anGFI%2FCaptura%20de%20pantalla%202023-04-17%20171402.png?alt=media&#x26;token=6840be47-dd8a-42c2-902e-6095d992f470" alt=""><figcaption></figcaption></figure>

[^1]: THIS NAME


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://buty-documentation.gitbook.io/home/guides/infinite-jobs/installation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
