> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fivenetwork.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# five-jobs

> Sistema de empregos legais (biscates) com agência central, missões, ranking, níveis por emprego e geral, e bônus por horas trabalhadas, com interface NUI em React.

O **five-jobs** é a central de empregos legais do servidor. O jogador interage com a **Agência de Empregos** (ponto físico no mapa via `sleepless_interact`), escolhe um emprego na interface NUI e cumpre rotas/coletas pela cidade para ganhar itens, dinheiro e XP.

## Funcionalidades

<CardGroup cols={2}>
  <Card title="15 empregos prontos" icon="briefcase">
    Minerador, jornaleiro, rebocador, cegonha, taxista, motorista, pescador, lixeiro, agricultor de trigo, agricultor de laranjas, lenhador, eletricista, entregador.
  </Card>

  <Card title="Dois sistemas de nível" icon="ranking-star">
    Nível geral do trabalhador e nível individual por emprego, cada um com seu multiplicador de recompensa.
  </Card>

  <Card title="Missões" icon="list-check">
    Missões por emprego que dão XP.
  </Card>

  <Card title="Bônus por horas trabalhadas" icon="clock">
    Dinheiro a cada faixa de horas, com reset periódico.
  </Card>

  <Card title="Ranking" icon="trophy">
    Os 15 jogadores com mais XP.
  </Card>

  <Card title="Troca de uniforme" icon="shirt">
    Troca automática de uniforme ao iniciar empregos que definem `clothes`.
  </Card>
</CardGroup>

<Warning>
  **Aviso do código** (`client-side/professions.lua`): a lógica de cada emprego é codificada em Lua na função `jobThread`. Adicionar um emprego totalmente novo exige programar essa lógica.
</Warning>

***

## Dependências

As dependências abaixo são necessárias para o funcionamento do recurso.

| Dependência          | Uso                                       |
| -------------------- | ----------------------------------------- |
| `vrp`                | Framework base (Proxy/Tunnel).            |
| `oxmysql`            | Banco de dados (tabela `five_jobs_data`). |
| `sleepless_interact` | Ponto de interação da agência.            |
| `five_logs`          | *Opcional*: logs de recompensas/bônus.    |

<Info>
  Sistemas externos esperados: `Notify`, `Progress`, `snt/animations/*`, `snt/inventory/*`, `garages:Delete`.
</Info>

***

## Configuração

<AccordionGroup>
  <Accordion title="config/config.lua — Agência de empregos" icon="building">
    ```lua theme={null}
    Config.jobsAgencies = {
        coords = { {-268.97,-956.1,31.22,18.57} },  -- pontos da agência
        blip   = { show = true, id = 642, color = 50, size = 0.8, name = "Agência de Empregos" },
        command = { enabled = true, name = "empregos", permission = {"cadmin","admin","founder"} }
    }
    ```

    <Warning>
      a sub-tabela `command` está definida mas **não é usada**, não existe `RegisterCommand` para abrir a agência. Ela só abre pelo ponto de interação físico.
    </Warning>
  </Accordion>

  <Accordion title="config/config.lua — Cores e dica na tela" icon="palette">
    ```lua theme={null}
    Config.markerColor = "#0143BB"  -- cor dos markers no mundo
    Config.ThemeColor  = "#0143BB"  -- cor da interface React
    Config.jobTipPosition = "bottom-left"  -- posição do balão de dica do emprego
    ```
  </Accordion>

  <Accordion title="config/config.lua — Níveis e XP" icon="chart-line">
    ```lua theme={null}
    -- XP por nível DENTRO do emprego (lido diretamente do config):
    Config.perJobLevels = { [1]=500, [2]=1200, [3]=2500, ... [10]=35000 }
    -- Bônus de recompensa por nível do emprego:
    Config.perLevelMultiplier = { [1]=0.05, [2]=0.10, ... [10]=1.50 }
    ```

    <Warning>
      o nível **geral** do trabalhador NÃO usa `Config.workerLevels`. O servidor usa uma tabela local fixa em `server-side/core.lua`:

      ```lua theme={null}
      local WorkerLevels = { [1] = 1000, [2] = 15000, [3] = 45000 }  -- só 3 níveis!
      ```

      Para alterar a curva do nível geral, edite essa tabela `WorkerLevels` no servidor (o `Config.workerLevels` sozinho não tem efeito).
    </Warning>

    **Cálculo do multiplicador:** a cada coleta, o bônus final é `multiplicador_do_emprego + multiplicador_geral`. A quantidade entregue é `base + floor(base * multiplicador)`.
  </Accordion>

  <Accordion title="config/config.lua — Bônus por horas trabalhadas" icon="clock">
    ```lua theme={null}
    Config.bonusByWorkedHours = {
        enabled = true,
        resetEveryDays = 12,       -- reinicia o progresso a cada 12 dias
        rewards = {
            { workedHours = 1,  reward = 400   },
            { workedHours = 75, reward = 67000 },
        }
    }
    ```
  </Accordion>

  <Accordion title="config/config.lua — Missões" icon="list-check">
    ```lua theme={null}
    Config.missions = {
        { id = 1, jobId = "motorista", title = "Pegar 25 passageiros",
          description = "...", target = 25, xp = 5000 },
    }
    ```

    `id` único, `jobId` válido (deve existir em `Config.professions`), `target` (nº de coletas), `xp` (XP geral).
  </Accordion>

  <Accordion title="config/professions.lua — Definição dos empregos" icon="briefcase">
    Cada chave é o `jobId`:

    ```lua theme={null}
    ["minerador"] = {
        name = "Mineração",
        description = "...",
        image = "minerador.png",
        expGainPerCollect = 50,             -- XP por coleta
        clothes = { ["male"] = {...}, ["female"] = {...} },  -- uniforme por gênero
        collectItems = {                     -- itens SEMPRE recebidos
            { item = "silver", amount = {1,3} },  -- {min,max} ou número fixo
        },
        extraItems = { { item = "diamond", amount = {1,1} } },  -- itens RAROS
        extraItemsChance = 5,               -- chance (%) de cair um extraItem
        requiredItems = { { items = {"fishingrod"}, consume = 1, notify = "..." } },
    }
    ```

    * `collectItems`: `item = "dollar"` entrega dinheiro. Quantidade fixa ou `{min,max}`.
    * `requiredItems`: itens exigidos/consumidos; `consume` desconta do inventário.
    * `clothes`: `{drawable, texture}` por componente. A roupa original é restaurada ao sair.

    <Note>
      **`displaySalary` / salário:** nenhum emprego define `displaySalary`, então o salário aparece como **0** na NUI. Para exibir, adicione `displaySalary = <numero>` na definição (campo cosmético; a recompensa real vem de `collectItems`).

      **`requiredLevel`** existe em vários empregos mas o servidor **não bloqueia** o início por nível (hoje é só informativo).
    </Note>
  </Accordion>

  <Accordion title="config/routes.lua — Rotas e coordenadas" icon="map-pin">
    Define, por `jobId`, coordenadas e parâmetros (`requiredVehicle`, `routePoints`, `crops`, `trees`, etc.). Edite para mudar onde cada emprego acontece.
  </Accordion>
</AccordionGroup>

***

## Comandos

<Info>
  Nenhum. Toda a interação é pela NUI (agência física no mapa) e pelo keybind F7 (cancelar emprego, remapeável nas configurações do FiveM).
</Info>

***

## Localizações

### Agência de Empregos (`config/config.lua`)

| Local                                               | Coordenadas                   | Tipo     |
| --------------------------------------------------- | ----------------------------- | -------- |
| Agência de Empregos (ponto de interação + blip 642) | -268.97, -956.1, 31.22, 18.57 | NPC/Blip |

<Note>
  O ped da agência também é spawnado por `five-modules` (peds.lua) em -268.97, -956.1, 31.22, 209.77.
</Note>

### Rotas e pontos por emprego (`config/routes.lua`)

Coordenadas de cada emprego (spawns, centrais, coletas/entregas). Empregos com muitos pontos repetidos têm a contagem indicada; a variável fica em `Config.routes["<jobId>"]`.

| Local                                                    | Coordenadas                                                                   | Tipo    |
| -------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
| minerador: central                                       | 1065.33, -1978.31, 31.02                                                      | Entrega |
| minerador: mineradora                                    | 2956.09, 2746.1, 43.53                                                        | Coleta  |
| minerador: pontos de mineração (`minerPoints`)           | 12 pontos, ex.: 2922.18, 2801.39, 41.7, 295.03                                | Coleta  |
| motorista: central/spawn                                 | 457.52, -599.04, 28.5, 102.84                                                 | Spawn   |
| motorista: paradas (`routePoints`)                       | 30 pontos, ex.: 399.33, -929.82, 29.32, 171.86                                | Rota    |
| pescador: porto (`portCoords`)                           | -1605.19, 5257.5, 2.08, 350.29                                                | Spawn   |
| pescador: áreas de pesca (`fishingAreas`)                | 8 pontos, ex.: -1658.41, 5184.73, -0.31, 312.39                               | Coleta  |
| lixeiro: central                                         | -329.27, -1525.74, 27.54, 76.4                                                | Spawn   |
| agricultor-trigo: fazenda (`farmCoords`)                 | 749.12, 6457.5, 31.61, 294.88                                                 | Spawn   |
| agricultor-trigo: plantações (`crops`)                   | 32 pontos, ex.: 742.66, 6455.79, 31.22                                        | Coleta  |
| agricultor-laranjas: fazenda (`farmCoords`)              | 350.31, 6519.81, 28.6, 124.32                                                 | Spawn   |
| agricultor-laranjas: árvores (`trees`)                   | 23 pontos, ex.: 377.1, 6506.98, 28.06, 213.65                                 | Coleta  |
| lenhador: floresta (`forestCoords`)                      | -1557.13, 4482.63, 19.96, 213.67                                              | Spawn   |
| lenhador: árvores (`trees`)                              | 65 pontos, ex.: -1555.36, 4471.77, 19.3, 188.81                               | Coleta  |
| eletricista: central                                     | 676.95, 56.93, 83.15, 294.21                                                  | Spawn   |
| entregador: restaurantes (`restaurants`)                 | 18 pontos, ex.: Pearls -1816.72, -1193.94, 14.31, 151.51                      | Coleta  |
| entregador: pontos de entrega (`deliveryPoints`)         | -500.79, 552.03, 120.61, 159.19 e -459.12, 536.99, 121.47, 174.53             | Entrega |
| entregador-jornais: spawn do veículo                     | -614.14, -935.19, 22.33, 102.05                                               | Spawn   |
| entregador-jornais: mercado                              | 46.7, -1749.71, 29.62, 102.05                                                 | Coleta  |
| entregador-jornais: pontos de entrega (`locations`)      | 73 pontos, ex.: 1223.03, -696.92, 60.8                                        | Entrega |
| reboque: spawn do veículo                                | 408.91, -1638.21, 29.28, 277.8                                                | Spawn   |
| reboque: entrega (`dropOff`)                             | 400.88, -1648.56, 29.1                                                        | Entrega |
| reboque: locais de coleta (`locations`)                  | 48 pontos, ex.: -625.45, -1657.5, 25.63, 243.78                               | Coleta  |
| cegonha: spawn do veículo                                | 1241.99, -3262.99, 5.53, 53.86                                                | Spawn   |
| cegonha: locais de entrega (`locations`)                 | 6 pontos, ex.: 1256.59, -3239.63, 5.17                                        | Entrega |
| taxista: spawn do veículo                                | 905.78, -165.15, 74.11, 73.71                                                 | Spawn   |
| taxista: pontos de passageiro (`locations`, Ped/Vehicle) | 29 pontos, ex.: Ped 1366.84, -593.63, 74.37 / Vehicle 1366.55, -590.32, 73.84 | Coleta  |

***

## Exports

O export abaixo é o único publicado pelo recurso (client-side; nenhum export server-side).

| Export            | Lado   | Descrição                                              |
| ----------------- | ------ | ------------------------------------------------------ |
| `SetJobTip(text)` | client | Define/atualiza o balão de dica na tela. `nil` oculta. |

***

## Banco de Dados

<Note>
  Tabela `five_jobs_data` criada automaticamente no start. Colunas principais: `characterId` (PK), `currentExp`, `currentLvl`, `missionsProgress` (JSON), `jobsExp` (JSON), `todayEarnings`, `totalEarnings`, `workedMinutes`, `bonusProgress` (JSON). Salvamento em lote a cada 10 minutos e no `playerDropped`.
</Note>

***

## Customização

### Adicionar um novo emprego

<Steps>
  <Step title="config/professions.lua">
    Adicione a definição (`name`, `expGainPerCollect`, `collectItems`, opcional `displaySalary`).
  </Step>

  <Step title="config/routes.lua">
    Adicione as coordenadas/rota.
  </Step>

  <Step title="client-side/professions.lua">
    Em `jobThread`, adicione um `elseif jobId == "meu_emprego" then` com a lógica (copie de um emprego parecido).
  </Step>
</Steps>

### Ajustar recompensas/níveis

* Recompensa real = `collectItems`/`extraItems` (config/professions.lua).
* Curva por emprego: `Config.perJobLevels` + `Config.perLevelMultiplier`.
* Curva geral: edite `WorkerLevels` no topo de `server-side/core.lua`.
* Bônus por horas e missões: `Config.bonusByWorkedHours` e `Config.missions`.
