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

> Sistema de lavagem de dinheiro com máquinas dinâmicas criadas in-game, limpadores, upgrades de eficiência e potência, e painel administrativo em NUI.

O **five-laundry** é o sistema de lavagem de dinheiro da base. Cada máquina converte dinheiro sujo em dinheiro limpo cobrando uma taxa, consumindo itens de limpeza e levando um tempo proporcional ao valor lavado.

As máquinas **não são cadastradas no config**: um administrador cria, posiciona e edita cada uma pelo painel in-game, e tudo fica salvo no banco de dados.

## Funcionalidades

<CardGroup cols={2}>
  <Card title="Máquinas dinâmicas" icon="location-dot">
    Criadas, movidas, editadas e removidas pelo painel administrativo, com posicionamento visual no mundo.
  </Card>

  <Card title="Lavagem com taxa" icon="money-bill-transfer">
    O jogador informa o valor, a máquina desconta a taxa configurada e devolve o restante em dinheiro limpo.
  </Card>

  <Card title="Limpadores" icon="flask">
    Cada lavagem consome itens de limpeza, abastecidos previamente na máquina pelos jogadores.
  </Card>

  <Card title="Upgrades" icon="arrow-up-right-dots">
    Eficiência aumenta o teto por lavagem; Potência reduz o tempo. Cinco níveis cada, pagos em dinheiro.
  </Card>

  <Card title="Prop animada" icon="soap">
    A máquina usa a secadora `bkr_prop_prtmachine_dryer`, que troca de modelo enquanto liga e enquanto lava.
  </Card>

  <Card title="Permissão por máquina" icon="lock">
    Cada máquina pode exigir uma permissão vRP específica para ser aberta.
  </Card>

  <Card title="Painel em NUI" icon="display">
    Interface React com telas de lavagem e de administração, cor de destaque configurável por máquina.
  </Card>

  <Card title="Logs completos" icon="scroll">
    Início, cancelamento, coleta, upgrades, limpadores e alterações de máquina, via `five_logs` ou webhook.
  </Card>
</CardGroup>

<Note>
  O recurso cria as próprias tabelas no MySQL ao iniciar. Não é necessário rodar SQL manualmente.
</Note>

***

## Dependências

<CardGroup cols={2}>
  <Card title="vrp" icon="layer-group">
    Framework base (`@vrp/lib/utils.lua`, `@vrp/config/Global.lua`).
  </Card>

  <Card title="oxmysql" icon="database">
    Persistência das máquinas, do estado das lavagens e das configurações (`@oxmysql/lib/MySQL.lua`).
  </Card>

  <Card title="sleepless_interact" icon="bullseye">
    Interação padrão com a máquina. Pode ser trocada por marcador no `client-side/thread.lua`.
  </Card>

  <Card title="five_logs" icon="scroll">
    Opcional. Sem ele, os logs caem automaticamente no fallback por webhook do Discord.
  </Card>
</CardGroup>

***

## Configuração

### config/config.lua

Arquivo enxuto: define apenas visual, moeda e o acesso ao painel administrativo.

```lua theme={null}
Laundry.DefaultThemeColor = "#0143bb"
Laundry.Logo = "https://cdn.fivenetwork.dev/IDCore/LOGO%20-%20BRANCO.png"

Laundry.Currency = {
    Prefix    = "R$ ",
    Suffix    = "",
    Separator = ".",
}

Laundry.Admin = {
    Command    = "laundryadmin",
    Permission = "Admin",
}

Laundry.Laundries = {}
```

| Campo                        | Descrição                                                               |
| ---------------------------- | ----------------------------------------------------------------------- |
| `DefaultThemeColor`          | Cor de destaque padrão do painel. Cada máquina pode sobrescrever a sua. |
| `Logo`                       | Imagem exibida no topo do painel. Use `""` para desativar.              |
| `Currency.Prefix` / `Suffix` | Texto exibido antes e depois dos valores.                               |
| `Currency.Separator`         | Separador de milhar dos valores exibidos.                               |
| `Admin.Command`              | Comando que abre o painel administrativo.                               |
| `Admin.Permission`           | Grupo/permissão exigido para abrir o painel administrativo.             |
| `Laundries`                  | Deixe vazio. As máquinas são gerenciadas pelo painel, não pelo arquivo. |

<Warning>
  Não adicione máquinas manualmente em `Laundry.Laundries`. Elas vivem na tabela `five_laundry_laundries` e são criadas pelo painel admin.
</Warning>

### Valores da lavagem

Os números da lavagem são padrões no `server-side/core.lua` e podem ser alterados **em jogo** pelo painel administrativo, ficando persistidos na tabela `five_laundry_settings`.

```lua theme={null}
Laundry.Items = {
    DirtyMoney = "dirtydollar", -- item consumido na lavagem
    CleanMoney = "dollar",      -- item entregue ao coletar
    Cleaner    = "water",       -- item usado como limpador
}

Laundry.Mathematics = {
    BaseValue       = 10000, -- valor de referência dos cálculos
    WashTime        = 5,     -- segundos por BaseValue lavado
    CleanerCost     = 1,     -- limpadores por BaseValue lavado
    TaxPercent      = 10,    -- taxa cobrada sobre o valor
    MinimumWashTime = 5,     -- piso de duração da lavagem
}

Laundry.Cancel = {
    RefundPercent  = 100,   -- percentual de dinheiro sujo devolvido ao cancelar
    RefundCleaners = false, -- devolve ou não os limpadores já consumidos
}
```

**Como cada valor entra na conta**

| Cálculo                 | Fórmula                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------- |
| Limpadores necessários  | `max(1, ceil((valor / BaseValue) * CleanerCost))`                                                  |
| Dinheiro limpo recebido | `floor(valor * (100 - TaxPercent) / 100)`                                                          |
| Duração da lavagem      | `max(MinimumWashTime, ceil(ceil(valor / BaseValue * WashTime) * (100 - bônus de potência) / 100))` |

<Info>
  Com os valores padrão, lavar R$ 100.000 consome 10 limpadores, devolve R$ 90.000 e leva 50 segundos em uma máquina sem upgrade de potência.
</Info>

### Upgrades

```lua theme={null}
Laundry.Upgrades = {
    Efficiency = {
        Enabled      = true,
        DefaultLimit = 1000000, -- teto por lavagem sem upgrade
        Levels = {
            [1] = { Limit = 2000000,  Price = 100000 },
            [2] = { Limit = 3000000,  Price = 100000 },
            [3] = { Limit = 5000000,  Price = 100000 },
            [4] = { Limit = 7500000,  Price = 100000 },
            [5] = { Limit = 10000000, Price = 100000 },
        },
    },

    Potency = {
        Enabled = true,
        Levels = {
            [1] = { TimeReducePercent = 10, Price = 100000 },
            [2] = { TimeReducePercent = 15, Price = 100000 },
            [3] = { TimeReducePercent = 20, Price = 100000 },
            [4] = { TimeReducePercent = 25, Price = 100000 },
            [5] = { TimeReducePercent = 30, Price = 100000 },
        },
    },
}
```

| Upgrade        | Efeito                                                                                  |
| -------------- | --------------------------------------------------------------------------------------- |
| **Eficiência** | Aumenta o valor máximo aceito em uma única lavagem. Sem upgrade, vale o `DefaultLimit`. |
| **Potência**   | Reduz o tempo da lavagem em um percentual, respeitando o `MinimumWashTime`.             |

Os upgrades são pagos com dinheiro do jogador (`Functions.Payment`) e pertencem à **máquina**, não a quem pagou.

### Interação (client-side/thread.lua)

O modo de interação é escolhido no topo do arquivo `client-side/thread.lua`.

```lua theme={null}
local Config = {
    Interaction = "target", -- "target" (sleepless_interact) ou "marker"

    Target = {
        label    = "Abrir Lavagem",
        icon     = "money-bill-wave",
        distance = 2.0,
    },

    Marker = {
        drawDistance     = 15.0,
        interactDistance = 1.5,
        key              = 38,   -- 38 = E
        markerType       = 27,
        size             = { x = 1.2, y = 1.2, z = 0.5 },
        color            = { r = 1, g = 67, b = 187, a = 150 },
        helpText         = "[E] Abrir Lavagem",
    },

    AutoCloseDistance = 4.0,
}
```

<Tip>
  Os dois modos terminam chamando `LaundryBridge.Open(id)`. Para plugar outro sistema de target, troque apenas a porta de entrada e mantenha essa chamada.
</Tip>

***

## Comandos

| Comando         | Permissão                                   | Descrição                                 |
| --------------- | ------------------------------------------- | ----------------------------------------- |
| `/laundryadmin` | `Laundry.Admin.Permission` (padrão `Admin`) | Abre o painel administrativo de máquinas. |

***

## Painel administrativo

<Steps>
  <Step title="Criar a máquina">
    No painel, use **Criar** e escolha se a máquina terá objeto físico. O jogo entra em modo de posicionamento para você fixar o local e a rotação.
  </Step>

  <Step title="Configurar">
    Defina nome, permissão exigida e cor de destaque da máquina. Sem permissão definida, qualquer jogador pode abrir.
  </Step>

  <Step title="Ajustar os números">
    Ainda no painel, altere itens, taxa, tempo, custo em limpadores e regras de cancelamento. As mudanças são salvas em `five_laundry_settings`.
  </Step>

  <Step title="Gerenciar">
    O painel também permite editar, teleportar até a máquina, atualizar a lista e remover máquinas.
  </Step>
</Steps>

***

## Fluxo de uma lavagem

<Steps>
  <Step title="Abastecer">
    Um jogador adiciona limpadores à máquina (item `Cleaner`). Eles ficam na máquina, disponíveis para qualquer lavagem seguinte.
  </Step>

  <Step title="Iniciar">
    O jogador informa o valor. O sistema valida o teto da eficiência, o dinheiro sujo em posse e os limpadores da máquina, cobra tudo e inicia a contagem.
  </Step>

  <Step title="Aguardar">
    A prop entra em animação e a máquina fica travada até o fim. Cancelar devolve o dinheiro sujo conforme `RefundPercent`.
  </Step>

  <Step title="Coletar">
    Ao terminar, alguém precisa coletar o dinheiro limpo antes que a máquina aceite uma nova lavagem.
  </Step>
</Steps>

<Warning>
  A lavagem é vinculada à máquina, não ao jogador: qualquer um com acesso à máquina pode coletar o resultado de uma lavagem finalizada.
</Warning>

***

## Banco de dados

| Tabela                   | Conteúdo                                                                      |
| ------------------------ | ----------------------------------------------------------------------------- |
| `five_laundry_laundries` | Máquinas criadas: nome, permissão, cor, se tem objeto e coordenadas.          |
| `five_laundry_machines`  | Estado de cada máquina: limpadores, níveis de upgrade e lavagem em andamento. |
| `five_laundry_settings`  | Configurações alteradas pelo painel administrativo (JSON).                    |

***

## Integração

O arquivo `config/functions.lua` é a ponte com o framework. Para portar o recurso, reescreva o corpo das funções mantendo nome, parâmetros e retorno.

| Função                                                     | Uso                                                                |
| ---------------------------------------------------------- | ------------------------------------------------------------------ |
| `Functions.Passport(source)` / `Functions.Source(user_id)` | Conversão entre source e identificador do jogador.                 |
| `Functions.FullName(user_id)`                              | Nome exibido nos logs.                                             |
| `Functions.HasPermission(user_id, permissions)`            | Acesso às máquinas com permissão configurada.                      |
| `Functions.HasGroup(user_id, group, level)`                | Acesso ao painel administrativo.                                   |
| `Functions.InventoryItemAmount(user_id, item)`             | Consulta de dinheiro sujo e limpadores. Retorna quantidade e slot. |
| `Functions.TakeItem` / `Functions.GiveItem`                | Consumo e entrega de itens.                                        |
| `Functions.Payment(user_id, amount)`                       | Cobrança dos upgrades.                                             |
| `Functions.Notify(source, tipo, mensagem, duração)`        | Notificação na interface do próprio recurso.                       |
| `Functions.Log(category, data)`                            | Envia para o `five_logs` ou, na ausência dele, para o webhook.     |

### Categorias de log

`LAVAGEM-INICIOU`, `LAVAGEM-CANCELOU`, `LAVAGEM-COLETOU`, `LAVAGEM-UPGRADE`, `LAVAGEM-LIMPADORES`, `CRIOU-LAVAGEM`, `EDITOU-LAVAGEM`, `REMOVEU-LAVAGEM` e `LAVAGEM-CONFIG`.

Cada categoria tem um webhook próprio em `config/webhooks.lua`, usado apenas quando o `five_logs` não está rodando.

***

## Customização

<AccordionGroup>
  <Accordion title="Trocar os itens da lavagem" icon="box">
    Altere `Laundry.Items` pelo painel administrativo. `DirtyMoney` é consumido, `CleanMoney` é entregue e `Cleaner` é o insumo abastecido na máquina. Os três precisam existir no `Item.lua` do vRP.
  </Accordion>

  <Accordion title="Deixar a lavagem mais lenta ou mais cara" icon="gauge">
    Suba `WashTime` para aumentar o tempo por `BaseValue`, `CleanerCost` para exigir mais limpadores e `TaxPercent` para reduzir o retorno. Para limitar o giro, baixe o `DefaultLimit` da eficiência.
  </Accordion>

  <Accordion title="Restringir uma máquina a uma facção" icon="lock">
    Ao criar ou editar a máquina, informe a permissão vRP no campo correspondente. Jogadores sem ela não conseguem abrir o painel daquela máquina.
  </Accordion>

  <Accordion title="Usar marcador em vez de target" icon="location-crosshairs">
    Troque `Interaction` para `"marker"` em `client-side/thread.lua`. O bloco `Marker` controla distância, tecla, tipo, tamanho, cor e texto flutuante.
  </Accordion>
</AccordionGroup>
