# Changelogs
Source: https://docs.squashcodes.com/pt/changelogs
Aqui você terá uma visão geral das ultimas atualizações de nossos resources
**OBS:** Somente atualizações a partir do dia 01/02/2025
# 📅 20/02/2025 - 02:45 | 📌 Versão 1.1 | 📱 sqh\_phone
#### Novidades:
* Evento configurável executado ao comprar o celular.
* Opção para desativar a bind do celular.
* Verificação opcional antes de abrir o celular.
* Possibilidade de alterar o ID dos objetos JBL e Celular.
* Sistema de autorização por IP para acessar funcionalidades exclusivas.
* Suporte à criação de redes Wi-Fi usando função exportável.
* Novos idiomas adicionados: Português (PT-PT), Espanhol (ES) e Inglês (EN).
* Lista de veículos (carros/motos) habilitados para trabalhar na UBER.
* Função configurável executada ao abrir/fechar o celular.
* Markers adicionados para compra de celular.
* Verificação de permissão para acessar o APP STAFF.
#### Correções e Melhorias:
* Correção no carregamento de postagens no Instagram.
* Correção no carregamento de postagens de Status.
* Ajuste no tamanho da barra de status ao atingir o limite.
* Correção no carregamento ao definir wallpaper personalizado.
* Corrigida falha nas apostas automáticas da Blaze.
* Problema resolvido com o ALT + TAB que deixava o celular transparente.
* Ajuste nas bordas que saíam para fora em alguns aplicativos.
* Correção de erros de texto e imagens.
* Correção no cache de imagens vindas de servidores diferentes.
* Curtidas e comentários em postagens do feed funcionando corretamente.
* Corrigido o bug onde a capa do celular voltava para preto após fechar e abrir.
* Voice agora está em 3D!
# Introdução
Source: https://docs.squashcodes.com/pt/introduction
Precisando de ajuda? está no lugar certo.
## Sobre a Squash Codes
A Squash Codes é mais do que apenas uma empresa; é a vanguarda da inovação na plataforma Multi Theft Auto (MTA). Nascemos da **paixão por transcender os padrões**, aliando **criatividade sem limites** com **rigor técnico** para criar recursos excepcionais para servidores. Nosso compromisso é constante: buscar inovação a cada passo e entregar uma experiência de jogo inigualável, enriquecendo cada momento dos jogadores no universo MTA. Com a Squash, a **excelência é a norma**.
## A documentação
A documentação da Squash Codes é um guia completo para o uso de nossos recursos. Aqui você encontrará tudo o que precisa para instalar, configurar e utilizar nossos recursos. Além disso, você encontrará artigos, notícias e outros assuntos fora do âmbito dos resources para MTA. Se você tiver alguma dúvida, não hesite em entrar em contato conosco.
Precisa de ajuda para colocar o seu produto no servidor? esse é o lugar certo!
Acompanhe as mudanças e atualizações em nossos resources através das changelogs.
Estamos aqui para te ajudar :) Se você não encontrar o que está procurando por aqui, veja esse tópico para descobrir a melhor forma de solicitar atendimento.
### Produtos
A documentação dos produtos é necessária para você que precisa de ajuda para configurar seu produto, aqui você irá encontrar tutoriais de configuração, funções exportáveis e seus respectivos exemplos de uso.
sqh\_phone
Precisa de ajuda para configurar seu sistema de celular? entre e confira.
sqh\_custom
Precisa de ajuda para configurar seu sistema de customização de personagens? entre e confira.
sqh\_groups
Precisa de ajuda para configurar seu sistema de grupos? entre e confira.
sqh\_accounts
Precisa de ajuda para configurar seu sistema de contas? entre e confira.
## A empresa
Confira abaixo informações sobre a empresa, como termos de compra.
Está em dúvida das obrigações que a SQUASH tem com você? que tal dar uma olhadinha em nossos termos de compra, onde terá acesso a direitos e deveres da parte fornecedora e consumidora.
# Instalação
Source: https://docs.squashcodes.com/pt/protection/install
Veja como instalar o módulo de proteção Squash no seu servidor MTA.
# Instalação do Squash Vulcan
Abaixo você encontra o guia de instalação do módulo de proteção **Squash Vulcan**, separado por sistema operacional:
Acesse a página de [Downloads](/pt/protection/modules) e selecione a versão **Windows x64** ou **x86**, conforme a arquitetura do seu servidor.
Após o download, coloque o módulo na pasta específica:
* **x64:** /x64/modules
* **x86:** /mods/deathmatch/modulesSe a pasta modules não existir, você pode criá-la manualmente.
Abra o arquivo mtaserver.conf e adicione a seguinte linha:
```xml mtaserver.conf theme={null}
```
O nome do arquivo deve ser idêntico ao baixado. Nomes diferentes impedem o carregamento do módulo.
Finalize reiniciando o servidor MTA para aplicar a proteção.
Acesse a página de [Downloads](/pt/protection/modules) e selecione a versão **Linux x64** ou **x86**, conforme a arquitetura do seu servidor.
Após o download, coloque o módulo na pasta apropriada:
* **x64:** /x64/modules
* **x86:** /mods/deathmatch/modulesSe a pasta modules não existir, você pode criá-la manualmente.
Adicione a linha abaixo no arquivo mtaserver.conf:
```xml mtaserver.conf theme={null}
```
O nome do arquivo deve ser exatamente igual ao baixado. Caso contrário, o módulo não será carregado.
Após configurar, reinicie o servidor MTA para ativar o Squash Vulcan.
Se tiver qualquer problema durante a instalação, acesse nossa [página de suporte](/company/support) ou entre em contato pelo Discord.
# Baixar Módulos
Source: https://docs.squashcodes.com/pt/protection/modules
Downloads oficiais do Squash Vulcan.
Escolha abaixo a versão do módulo **Squash Vulcan** compatível com o seu servidor.
Versão: 1.0.0\
Atualizado em: 7 de maio de 2025
Download
Versão: 1.0.0\
Atualizado em: 7 de maio de 2025
Download
Versão: 1.0.0\
Atualizado em: 7 de maio de 2025
Download
Versão: 1.0.0\
Atualizado em: 7 de maio de 2025
Download
⚠️ Após o download, é obrigatório configurar o módulo no mtaserver.conf para ativar a proteção. Veja como fazer isso na [página de instalação](/pt/protection/install).
# Introdução
Source: https://docs.squashcodes.com/pt/protection/overview
Entenda como funciona a proteção dos resources da Squash Codes.
# 🌋 SQUASH VULCAN
O **Squash Vulcan** é o núcleo de proteção mais avançado já criado para servidores MTA. Desenvolvido do zero, ele age como uma camada invisível entre o servidor e qualquer tentativa de engenharia reversa, debug, modificação ou acesso não autorizado aos arquivos da Squash. Focado na segurança de você, nosso cliente, o Vulcan é a resposta definitiva para os desafios de proteção enfrentados pelas empresas no MTA.
🔥 **Vulcan não só protege — ele reage.**
***
## Compatibilidade
Suporte oficial à versão **MTA 1.6.0 r22890+**. Caso você utilize uma versão anterior, entre em contato com o suporte da sua hospedagem para atualizar o servidor. Confira mais na [Wiki Oficial do MTA](https://wiki.multitheftauto.com/wiki/Server_Manual).
Compatível com **Windows x64 e x86**. Recomendado o uso com servidores dedicados ou máquinas virtuais com virtualização habilitada.
Totalmente compatível com **Linux x64 e x86**, testado em ambientes Debian, Ubuntu e containers com Docker.
***
Pronto para liberar o poder do Vulcan? Vá para a página [📦 Baixar Módulos](/pt/protection/modules).
# Account System
Source: https://docs.squashcodes.com/pt/resources/accounts
Adquiriu o resource de contas e está com dúvidas do sistema? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
* [getLoggedPlayerMainName](#getLoggedPlayerMainName) --> `Retorna o nome da conta principal do jogador`
* [getLoggedPlayerPersonName](#getLoggedPlayerPersonName) --> `Retorna o nome do personagem que o jogador está conectado`
* [getLoggedPlayerInfos](#getLoggedPlayerInfos) --> `Retorna uma tabela com o nome da conta principal e o nome do personagem`
* [getCharacterInfos](#getCharacterInfos) --> `Retorna todas as informações do personagem (nome, sobrenome, avatar, gênero, idade, etc...)`
* [setPlayerCityPosition](#setPlayerCityPosition) --> `Seta o player na posição da cidade natal do mesmo`
* [manageUserCoins](#manageUserCoins) --> `Seta, remove ou adiciona coins a um usuário`
* [getUserCoins](#getUserCoins) --> `Retorna a quantidade de coins de um usuário`
* [getUserMainAvatar](#getUserMainAvatar) --> `Pega o avatar da conta principal de um usuário`
* [getPlayerAvatar](#getPlayerAvatar) --> `Pega o avatar do personagem que o player está logado`
## getLoggedPlayerMainName
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getLoggedPlayerMainName('ped' theElement)
```
**Required arguments**
* ***theElement:*** Elemento que você irá obter o nome da conta principal
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver o nome de sua conta principal
```lua theme={null}
addCommandHandler( 'accountname', -- Exemplo: /accountname
function(player, _)
local mainName = getLoggedPlayerMainName(player)
outputChatBox('Sua conta principal se chama: '..mainName, player, 255, 255, 255)
end
)
```
## getLoggedPlayerPersonName
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getLoggedPlayerPersonName('ped' theElement)
```
**Required arguments**
* ***theElement:*** Elemento que você irá obter o nome do personagem
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver o nome do personagem que está conectado
```lua theme={null}
addCommandHandler( 'personname', -- Exemplo: /personname
function(player, _)
local personName = getLoggedPlayerPersonName(player)
outputChatBox('O seu personagem atual se chama: '..personName, player, 255, 255, 255)
end
)
```
## getLoggedPlayerInfos
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getLoggedPlayerInfos('ped' theElement)
```
**Required arguments**
* ***theElement:*** Elemento que você irá obter as informações do personagem e conta principal
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver o nome do personagem que está conectado e de sua conta
```lua theme={null}
addCommandHandler( 'infos', -- Exemplo: /infos
function(player, _)
local personName = getLoggedPlayerInfos(player)
outputChatBox('O seu personagem atual se chama: '..personName['personName'].. ' sua conta: '..personName['mainName'], player, 255, 255, 255)
end
)
```
## getCharacterInfos
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getCharacterInfos('string' mainName, 'string' character)
```
**Required arguments**
* ***mainName:*** Nome da conta principal da qual você quer obter as informações
* ***character:*** Nome do personagem de qual você quer obter as informações (EX: JoohnWiick)
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver sua idade
```lua theme={null}
addCommandHandler( 'idade', -- Exemplo: /infos
function(player, _)
local mainData = getElementData(player, 'accounts:mainName')
local playerData = getElementData(player, 'accounts:personName')
if (mainData and playerData) then
local character = getCharacterInfos(mainData, playerData)
if (character['age']) then
outputChatBox('Você tem: '..character['age'].. ' anos de idade', player, 255, 255, 255)
end
end
end
)
```
## setPlayerCityPosition
**Syntax**
```lua theme={null}
exports['sqh_accounts']:setPlayerCityPosition('ped' player, 'string' mainName, 'string' personName)
```
**Required arguments**
* ***player:*** Jogador que você deseja setar na posição da cidade natal
* ***mainName:*** Nome da conta principal da qual você quer obter a cidade natal
* ***character:*** Nome do personagem de qual você quer obter a cidade natal
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver sua idade
```lua theme={null}
addCommandHandler( 'city', -- Exemplo: /infos
function(player, _)
local mainData = getElementData(player, 'accounts:mainName')
local playerData = getElementData(player, 'accounts:personName')
if (mainData and playerData) then
setPlayerCityPosition(player, mainData, playerData)
outputChatBox('Você chegou na sua cidade natal', player, 255, 255, 255)
end
end
)
```
## manageUserCoins
**Syntax**
```lua theme={null}
exports['sqh_accounts']:manageUserCoins('string' mainName, 'string' typeManage, 'number' amount)
```
**Required arguments**
* ***mainName:*** Nome da conta principal que você deseja alterar os coins
* ***typeManage:*** Qual ação você deseja realizar (set, add ou remove)
* ***amount:*** Quantidade que você deseja adicionar/remover/setar
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador gerenciar x coins para ele mesmo
```lua theme={null}
addCommandHandler( 'coins', -- Exemplo: /coins add 1000
function(player, _, type, amount)
local mainData = getElementData(player, 'accounts:mainName')
if (mainData) then
manageUserCoins(mainData, type, tonumber(amount))
outputChatBox('Você gerenciou '..amount.. ' coins', player, 255, 255, 255)
end
end
)
```
## getUserCoins
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getUserCoins('string' mainName)
```
**Required arguments**
* ***mainName:*** Nome da conta principal que você deseja obter os coins
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador ver quantos coins ele possui
```lua theme={null}
addCommandHandler( 'vercoins', -- Exemplo: /vercoins
function(player, _)
local mainData = getElementData(player, 'accounts:mainName')
if (mainData) then
local coins = getUserCoins(mainData)
outputChatBox('Você possui '..coins.. ' coins', player, 255, 255, 255)
end
end
)
```
## getUserMainAvatar
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getUserMainAvatar('string' mainName)
```
**Required arguments**
* ***mainName:*** Nome da conta principal que você deseja obter o avatar
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador retornar o numero do seu avatar
```lua theme={null}
addCommandHandler( 'avatar', -- Exemplo: /avatar
function(player, _)
local mainData = getElementData(player, 'accounts:mainName')
if (mainData) then
local avatar = getUserMainAvatar(mainData)
outputChatBox('Seu avatar é o: '..avatar, player, 255, 255, 255)
end
end
)
```
## getPlayerAvatar
**Syntax**
```lua theme={null}
exports['sqh_accounts']:getPlayerAvatar('ped' theElement)
```
**Required arguments**
* ***theElement:*** Player que você deseja obter o avatar do personagem logado
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador retornar o numero do avatar do seu personagem logado
```lua theme={null}
addCommandHandler( 'avatar', -- Exemplo: /avatar
function(player, _)
local avatar = getPlayerAvatar(player)
outputChatBox('Seu avatar é o: '..avatar, player, 255, 255, 255)
end
)
```
# Como configurar o resource?
# Exports Auth Discord System
Source: https://docs.squashcodes.com/pt/resources/authdiscord/exports
Adquiriu o Auth Discord System e está com dúvidas sobre as funções exportáveis? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
O Auth Discord System é um sistema completo de autenticação de jogadores via Discord para servidores MTA. O jogador entra no servidor, recebe um código de confirmação, digita no canal do Discord e a conta é liberada automaticamente — sem precisar criar senha ou login manual.
Com as funções exportadas, você pode:
* Verificar manualmente se um player já passou pela autenticação e abrir o painel caso não tenha;
* Adicionar cargos no Discord de um player autenticado diretamente por script;
* Obter o Discord ID de qualquer player autenticado (útil para cruzar dados com sistemas externos);
* Forçar a sincronização do nome do Discord com o nome do player no jogo.
## Funções Exportadas
### Server-side
* [verifyPlayerAccount](#verifyplayeraccount) -> `Verifica se o player está autenticado e abre o painel caso não esteja`
* [addRoleDiscordToPlayer](#addrolediscordtoplayer) -> `Adiciona um cargo no Discord ao player autenticado`
* [getPlayerDiscordID](#getplayerdiscordid) -> `Retorna o Discord ID do player autenticado`
* [vinculateDiscordName](#vinculatediscordname) -> `Sincroniza o nome do Discord com o nome do player no jogo`
***
## verifyPlayerAccount
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_authdiscord']:verifyPlayerAccount(player)
```
**Required arguments**
* `player` (`player`): jogador a ser verificado.
**Comportamento**
* Consulta o banco de dados pelo serial do player.
* Se o player **já está registrado**, abre a tela de `confirmAccount` (aguardando entrada no servidor Discord).
* Se o player **não está registrado ainda**, gera um código único e abre a tela inicial de autenticação com o código exibido.
* Esta função é chamada automaticamente nos eventos `onPlayerJoin` e `onPlayerLogin` conforme as opções `config.onPlayerJoin` e `config.onPlayerLogin`. Use a export para chamadas manuais (ex.: ao trocar de personagem).
**Return**
* Não há retorno explícito. A ação ocorre via triggers client-side.
**Example**
```lua theme={null}
-- SERVER-SIDE (abrir autenticação ao trocar de personagem)
addEventHandler('onCharacterSwitch', root, function(player)
exports['sqh_authdiscord']:verifyPlayerAccount(player)
end)
```
```lua theme={null}
-- SERVER-SIDE (forçar re-verificação por comando de staff)
addCommandHandler('verificarconta', function(player, _, targetName)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_authdiscord']:verifyPlayerAccount(target)
outputChatBox('Verificação enviada para ' .. targetName, player)
end
end)
```
***
## addRoleDiscordToPlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_authdiscord']:addRoleDiscordToPlayer(player, roleID)
```
**Required arguments**
* `player` (`player`): jogador autenticado que receberá o cargo.
* `roleID` (`string`): ID do cargo no Discord a ser adicionado.
**Comportamento**
* Envia uma requisição à API do bot do Discord para adicionar o cargo ao usuário correspondente ao player.
* Só funciona se o player tiver uma sessão ativa (estiver autenticado e online).
* A operação é assíncrona — o cargo é adicionado em background via `fetchRemote`.
**Return**
* Não há retorno explícito na função (a resposta é processada internamente pelo callback do `fetchRemote`).
**Example**
```lua theme={null}
-- SERVER-SIDE (dar cargo VIP ao comprar no sistema de loja)
addEventHandler('onPlayerBuyVIP', root, function(player)
exports['sqh_authdiscord']:addRoleDiscordToPlayer(player, '1234567890123456789')
end)
```
```lua theme={null}
-- SERVER-SIDE (dar cargo de facção ao entrar)
addEventHandler('onPlayerJoinFaction', root, function(player, factionID)
if factionID == 1 then
exports['sqh_authdiscord']:addRoleDiscordToPlayer(player, '9876543210987654321')
end
end)
```
***
## getPlayerDiscordID
**Side:** `server`
**Syntax**
```lua theme={null}
local discordID = exports['sqh_authdiscord']:getPlayerDiscordID(player)
```
**Required arguments**
* `player` (`player`): jogador autenticado.
**Comportamento**
* Retorna o Discord ID (clientID) do player a partir do cache em memória carregado na autenticação.
* O cache é preenchido quando o player se autentica ou quando o resource reinicia (buscando dados do banco).
* Se o player não estiver autenticado ou não tiver sessão ativa, retorna `false`.
**Return**
* `string` com o Discord ID do player, ex: `"123456789012345678"`.
* `false` se o player não estiver autenticado ou não tiver Discord ID registrado.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('meudiscord', function(player)
local discordID = exports['sqh_authdiscord']:getPlayerDiscordID(player)
if discordID then
outputChatBox('Seu Discord ID: ' .. discordID, player)
else
outputChatBox('Você não está autenticado no Discord.', player)
end
end)
```
```lua theme={null}
-- SERVER-SIDE (integrar com sistema de bot externo)
addEventHandler('onPlayerLogin', root, function()
local discordID = exports['sqh_authdiscord']:getPlayerDiscordID(source)
if discordID then
triggerEvent('syncDiscordRoles', root, source, discordID)
end
end)
```
***
## vinculateDiscordName
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_authdiscord']:vinculateDiscordName(player)
```
**Required arguments**
* `player` (`player`): jogador autenticado que terá o nome sincronizado.
**Comportamento**
* Envia uma requisição à API para atualizar o nome do player no Discord de acordo com o ID do jogo retornado por `config.infosPlayer.getIDFunction(player)`.
* Utilizado para manter o nome/nickname do Discord sincronizado com as informações do servidor.
* Depende de `config.infosPlayer.setIDInDiscord` estar configurado para incluir o ID do jogo no nome.
* O sistema já chama esta função automaticamente no `onPlayerLogin` quando `config.discordInfos.setDiscordNameInGame = true`. Use a export para sincronizações manuais específicas.
**Return**
* Não há retorno explícito. A sincronização ocorre em background.
**Example**
```lua theme={null}
-- SERVER-SIDE (sincronizar nome ao mudar de personagem)
addEventHandler('onPlayerSelectCharacter', root, function(player)
setTimer(function()
exports['sqh_authdiscord']:vinculateDiscordName(player)
end, 2000, 1)
end)
```
```lua theme={null}
-- SERVER-SIDE (forçar sincronização por comando)
addCommandHandler('sincdiscord', function(player)
exports['sqh_authdiscord']:vinculateDiscordName(player)
outputChatBox('Sincronização com Discord enviada!', player)
end)
```
***
## Observações
* Todas as exports só funcionam corretamente após o resource ser iniciado e a licença validada.
* As funções `addRoleDiscordToPlayer` e `vinculateDiscordName` requerem que o player esteja com sessão ativa no cache (autenticado durante a sessão atual). Players que entraram antes de um `restart` do resource terão o cache recarregado automaticamente.
* `getPlayerDiscordID` é a export mais comum para integrações — use sempre que precisar do Discord ID de um player em outro script.
* Para `addRoleDiscordToPlayer` funcionar, o bot do Discord deve estar corretamente configurado e online.
# Configurações Auth Discord System
Source: https://docs.squashcodes.com/pt/resources/authdiscord/settings
Guia completo do config/settings.lua do Auth Discord System.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Precisa integrar o Auth Discord System com outro script? Clique aqui
## Sobre o sistema
O Auth Discord System autentica jogadores via Discord automaticamente — sem login manual, sem senha. O jogador recebe um código no jogo, digita no canal do Discord e a conta é liberada.
## Visão Geral
Este guia cobre **todo o arquivo** `config/settings.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você saber quando usar `true` ou `false`.
* Você configurar o sistema sem precisar entrar em detalhes técnicos.
## Antes de Começar
* Arquivo de configuração: `config/settings.lua`
* Depois de alterar a config: reinicie o resource (`restart sqh_authdiscord`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## 1) `license`
Configuração da licença de ativação do sistema.
| Opção | Descrição |
| --------------- | ---------------------------------------------------------------- |
| `license.Email` | E-mail da conta na Squash Company utilizado na compra do produto |
| `license.Key` | Chave de licença do produto |
```lua theme={null}
license = {
["Email"] = "seu@email.com",
["Key"] = "SQUASH-xxxx-xxxx",
}
```
***
## 2) `config.infobox`
Funções de notificação. Configure aqui o sistema de alert/toast do seu servidor.
| Callback | Quando é chamado |
| -------- | --------------------------------------------------------------------------- |
| `server` | Notificações enviadas pelo lado server (recebe `source`, `message`, `type`) |
| `client` | Notificações enviadas pelo lado client (recebe `source`, `message`, `type`) |
`type` pode ser: `'success'`, `'error'`, `'info'`, `'warning'`
```lua theme={null}
config.infobox = {
['server'] = function(source, message, type)
exports["s_infobox"]:addInsInfobox(source, message, type)
end,
['client'] = function(source, message, type)
exports["s_infobox"]:addIncInfobox(message, type)
end,
}
```
***
## 3) `config.events`
### `onVerifiedPlayer`
Callback executado quando o player é verificado/autenticado com sucesso.
```lua theme={null}
config.events = {
onVerifiedPlayer = function(player)
-- executado assim que o jogador finaliza a autenticação
-- ex.: abrir seletor de personagens, liberar acesso ao servidor
exports['sqh_multicharacters']:openPanelCharacters(player)
end,
}
```
> **Importante**: Este é o ponto central da integração. Coloque aqui a função que deve rodar após o login — normalmente a abertura do painel de personagens ou liberação do jogador.
***
## 4) Opções de Abertura Automática
Define quando o painel de autenticação deve abrir automaticamente.
| Opção | `true` | `false` |
| ---------------------- | ------------------------------------------------------------------------------ | ----------------------------------- |
| `config.onPlayerJoin` | Abre o painel assim que o jogador **entra no servidor** (`onPlayerJoin`) | Não abre automaticamente na entrada |
| `config.onPlayerLogin` | Abre o painel assim que o jogador **faz login na conta MTA** (`onPlayerLogin`) | Não abre automaticamente no login |
> **Recomendação**: Em servidores com sistema de login próprio, use `onPlayerLogin = true` e `onPlayerJoin = false`.
***
## 5) `config.discordLink`
Link de convite do Discord exibido no painel de autenticação.
```lua theme={null}
config.discordLink = 'https://discord.gg/seuservidor'
```
***
## 6) `config.createAccountMTA`
| Opção | `true` | `false` |
| ------------------ | ---------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `createAccountMTA` | Cria automaticamente uma conta MTA para o jogador após o registro e faz login automático | Não cria conta MTA — você gerencia o login manualmente |
> Se `true`, o campo de nome digitado no Discord será usado como nome da conta MTA. Por isso, ao configurar o bot do Discord, ative a opção de digitar o nome.
***
## 7) `config.timeVerify`
Tempo em **segundos** que o sistema aguarda antes de verificar se o player entrou no Discord do servidor.
```lua theme={null}
config.timeVerify = 5 -- padrão: 5 segundos
```
***
## 8) `config.playerInDiscord`
| Opção | `true` | `false` |
| ----------------- | ------------------------------------------------------------------------ | ------------------------------------------------- |
| `playerInDiscord` | Verifica se o jogador está no servidor Discord antes de liberar o acesso | Libera o acesso sem verificar presença no Discord |
> Com `true`, se o player não estiver no Discord, a tela de "você precisa entrar no Discord" é exibida.
***
## 9) `config.blockChangeName`
| Opção | `true` | `false` |
| ----------------- | ---------------------------------------- | --------------------------------------- |
| `blockChangeName` | Impede que o jogador mude o nome no jogo | O jogador pode mudar o nome normalmente |
> Se `false` e `config.infosPlayer.changeNameActive = true`, a mudança de nome no jogo será sincronizada automaticamente com o Discord.
***
## 10) `config.discordInfos`
### 10.1 Cargos automáticos
| Opção | Descrição |
| ------------------------- | ------------------------------------------------------------------------------ |
| `onRegisterSetOffices` | Lista de IDs de cargos **dados** ao jogador quando ele é registrado/verificado |
| `onRegisterRemoveOffices` | Lista de IDs de cargos **removidos** do jogador quando ele é registrado |
```lua theme={null}
discordInfos = {
onRegisterSetOffices = {'ID_DO_CARGO_MEMBRO'},
onRegisterRemoveOffices = {'ID_DO_CARGO_NAO_VERIFICADO'},
}
```
### 10.2 Troca de serial
| Opção | Descrição |
| -------------- | ----------------------------------------------------------------------------- |
| `changeSerial` | Lista de Discord IDs autorizados a trocar o serial vinculado à conta pelo bot |
Deixe vazio `{}` se não quiser usar este recurso.
### 10.3 Canais do Discord
| Opção | Descrição |
| ---------------- | ---------------------------------------------------------------------------- |
| `channelLogs` | ID do canal onde o bot registrará logs de autenticações |
| `channelMessage` | ID do canal onde o bot enviará as mensagens de verificação para os jogadores |
### 10.4 Formatação e nome
| Opção | Tipo | Descrição |
| ---------------------- | --------- | ------------------------------------------------------------------------------------------------ |
| `formatID` | `string` | Formato do nome exibido no Discord após autenticação. Use `$id` e `$name`. Ex: `"{$id} - $name"` |
| `playerName` | `boolean` | Se `true`, o bot pedirá ao jogador para digitar seu nome durante o processo |
| `setDiscordNameInGame` | `boolean` | Se `true`, ao entrar no jogo o nome do Discord será aplicado no nick do jogador |
### 10.5 `translates` — Textos do bot no Discord
Textos exibidos pelo bot durante o fluxo de autenticação.
| Opção | Descrição |
| -------------------- | -------------------------------------------------------------------------- |
| `descriptionMessage` | Texto principal da mensagem enviada no canal (suporta Markdown do Discord) |
| `imageMain` | URL da imagem exibida na mensagem principal |
| `imageFooter` | URL da imagem de rodapé |
### 10.6 `messages` — Mensagens operacionais
Mensagens enviadas em situações específicas do fluxo.
| Chave | Quando é exibida |
| ------------------ | -------------------------------------------- |
| `confirmInfos` | Ao solicitar confirmação de dados |
| `digitCode` | Ao pedir o código de verificação |
| `register_success` | Após a conta ser registrada com sucesso |
| `name_unavailable` | Quando o nome escolhido já está em uso |
| `code_failed` | Quando ocorre falha na confirmação do código |
***
## 11) `config.nameMainConfigs`
Configuração do comando auxiliar para obter o nome da conta interna.
| Opção | Tipo | Descrição |
| ---------------- | ------------------ | ----------------------------------------------------------------------------------------------- |
| `commandActive` | `boolean` | Ativa o comando `/vernomedaconta`. Deixe `true` apenas durante a configuração inicial do serial |
| `havePermission` | `function(player)` | Retorna `true` se o player tem permissão para usar o comando |
> Após usar o comando para configurar o serial, volte `commandActive = false`.
```lua theme={null}
config.nameMainConfigs = {
commandActive = false,
havePermission = function(player)
return isObjectInACLGroup('user.'..getAccountName(getPlayerAccount(player)), aclGetGroup('Admin'))
end
}
```
***
## 12) `config.infosPlayer`
Configurações sobre o nome e ID do player no jogo.
### 12.1 `getNameOption` — Como o nome é definido
| Valor | Comportamento |
| ---------------- | -------------------------------------------------------------------------- |
| `'Discord'` | O nome do Discord do jogador é usado como nome no jogo |
| `'Game'` | O nome atual do jogador no jogo é mantido (uso de `getNamePlayerFunction`) |
| `'DiscordDigit'` | O nome digitado pelo jogador no input do Discord é usado |
```lua theme={null}
config.infosPlayer.getNameOption = 'Discord'
```
### 12.2 `getNamePlayerFunction`
Função usada quando `getNameOption = 'Game'` para obter o nome do jogador.
```lua theme={null}
config.infosPlayer.getNamePlayerFunction = function(player)
return getPlayerName(player)
end
```
### 12.3 Sincronização de nome e ID
| Opção | `true` | `false` |
| ------------------ | ------------------------------------------------------------------------------------- | ------------------------------------------- |
| `changeNameActive` | Quando o jogador mudar o nome no jogo, o nome no Discord é atualizado automaticamente | Mudança de nome no jogo não afeta o Discord |
| `setIDInDiscord` | O ID do jogador (retornado por `getIDFunction`) é incluído no nome do Discord | O ID não é adicionado ao nome |
```lua theme={null}
config.infosPlayer.getIDFunction = function(player)
return getElementData(player, 'ID') or 'N/A'
end
```
***
## 13) `config.designInfos`
Configurações visuais do painel de autenticação.
| Opção | Tipo | Descrição |
| ------------ | -------- | --------------------------------------------------------------- |
| `design` | `number` | Escolha o layout do painel: `1` ou `2` (são designs diferentes) |
| `color_main` | `string` | Cor principal do painel (hex). Ex: `'#FF145B'` |
### 13.1 `logo`
| Opção | Tipo | Descrição |
| -------------- | --------- | ----------------------------------------------------------------- |
| `x`, `y` | `number` | Posição da logo na tela |
| `w`, `h` | `number` | Largura e altura da logo |
| `image` | `string` | Caminho para o arquivo de imagem |
| `primaryColor` | `boolean` | Se `true`, a logo recebe a cor principal definida em `color_main` |
### 13.2 `socialMedia`
Lista de links de redes sociais exibidos no painel.
```lua theme={null}
config.designInfos.socialMedia = {
{icon = 'discord', url = 'https://discord.gg/seuservidor'},
{icon = 'youtube', url = 'https://youtube.com/seucanal'},
{icon = 'instagram', url = 'https://instagram.com/seuservidor'},
}
```
***
## 14) `colors`
Paleta de cores da interface de autenticação.
| Opção | Descrição |
| -------------------- | ---------------------------------------------------------- |
| `white` | Cor branca base |
| `black` | Cor preta base |
| `primary` | Cor principal (herdada de `config.designInfos.color_main`) |
| `pink` | Cor rosa de destaque |
| `primaryText` | Cor principal de texto |
| `secondaryText` | Cor secundária de texto (40% de opacidade) |
| `pinkBackground` | Fundo rosa com baixa opacidade (15%) |
| `pinkStroke` | Borda rosa (35%) |
| `background_opacity` | Fundo escuro do painel (90% de opacidade) |
| `primary_opacity` | Fundo da cor primária com baixa opacidade (7%) |
| `whiteOpacity` | Branco com baixa opacidade (4%) |
| `whiteStroke` | Borda branca (8%) |
| `whiteBorder` | Borda branca mais visível (20%) |
Formato das cores: `'#RRGGBB XX%'` onde `XX%` é a opacidade.
> As cores `primary` e `primary_opacity` são geradas automaticamente a partir de `config.designInfos.color_main`.
***
## 15) `translate`
Define o idioma padrão e os textos da interface do painel.
### 15.1 Idioma padrão
| Opção | Valor | Descrição |
| -------------------- | --------- | --------------------- |
| `translate.language` | `'PT'` | Português (Brasil) |
| `translate.language` | `'EN'` | Inglês |
| `translate.language` | `'ES'` | Espanhol |
| `translate.language` | `'TR'` | Turco |
| `translate.language` | `'HU'` | Húngaro |
| `translate.language` | `'PT-PT'` | Português de Portugal |
```lua theme={null}
translate = {
language = 'PT',
}
```
### 15.2 Textos por idioma
Cada bloco de idioma contém as chaves de texto exibidas na interface.
| Chave | Onde aparece |
| ---------------------- | --------------------------------------------------------- |
| `code_confirm` | Título da tela de código de confirmação |
| `click_copy` | Instrução abaixo do código |
| `copy_discord` | Botão de copiar link do Discord |
| `copy_code` | Botão de copiar código |
| `digit_code_text` | Texto explicativo de como usar o código no Discord |
| `left_server` | Botão de sair do servidor |
| `disconnect` | Texto de desconectar |
| `confirming_account` | Título da tela de confirmação em andamento |
| `logged_success` | Notificação de login realizado com sucesso |
| `waiting_join` | Tela de aguardando entrada no Discord |
| `necessarie_join` | Mensagem quando o jogador não está no Discord do servidor |
| `click_to_copy` | Texto de ação ao clicar no código |
| `sinc_discord_success` | Notificação de sincronização com Discord bem-sucedida |
| `sinc_name_discord` | Notificação de nome sincronizado com Discord |
***
## Dicas Finais
* Após qualquer alteração no `config/settings.lua`, reinicie o resource com `restart sqh_authdiscord`.
* O `config.events.onVerifiedPlayer` é o coração da integração — sem configurá-lo corretamente, o player será autenticado mas não terá acesso liberado no servidor.
* Se usar `createAccountMTA = true`, certifique-se de que o bot do Discord está configurado para pedir o nome do jogador (`playerName = true`), pois o nome digitado será o nome da conta MTA.
* Para sincronização de nome com Discord funcionando corretamente, `blockChangeName` deve ser `false` e `infosPlayer.changeNameActive` deve ser `true`.
* O `nameMainConfigs.commandActive` deve ficar `false` em produção — ative apenas durante a configuração inicial do serial.
# Exports Craft System
Source: https://docs.squashcodes.com/pt/resources/craft-system/exports
Adquiriu o Craft System e está com dúvidas do sistema? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Craft System é unir flexibilidade, persistência e controle total sobre as bancadas de crafting do seu servidor.
O dono do servidor tem poder absoluto para criar bancadas fixas no mapa, conceder bancadas para jogadores, gerenciar upgrades e integrar com qualquer sistema de inventário.
Com as funções exportadas, você pode:
* Criar e deletar bancadas de crafting diretamente por script;
* Forçar o spawn de uma bancada em posição fixa ou deixar o player posicioná-la com preview;
* Gerenciar upgrades como combustível, slots de fabricação e fabricação paralela;
* Consultar todas as mesas ativas, buscar uma mesa por objeto ou por marker;
* Integrar o sistema de craft com empregos, missões, sistemas VIP e muito mais.
## Funções Exportadas
### Server-side
* [createCraftTable](#createcrafttable) -> `Cria uma nova bancada de crafting`
* [deleteCraftTable](#deletecrafttable) -> `Deleta uma bancada de crafting`
* [addCraftTableUpgrade](#addcrafttableupgrade) -> `Adiciona ou atualiza um upgrade em uma bancada`
* [forceCraftTableSpawn](#forcecrafttablespawn) -> `Força o spawn de uma bancada sem preview`
* [spawnCraftTableWithPreview](#spawncrafttablewithpreview) -> `Inicia o posicionamento de uma bancada com preview para o player`
* [spawnWithPreview](#spawnwithpreview) -> `Alias de spawnCraftTableWithPreview`
* [spawnWithPreviewByOwner](#spawnwithpreviewbyowner) -> `Inicia preview buscando a mesa do owner automaticamente`
* [getSpawnedCraftTables](#getspawnedcrafttables) -> `Retorna todas as bancadas atualmente spawnadas`
* [getCraftTableByObject](#getcrafttablebyobject) -> `Busca os dados de uma bancada pelo elemento objeto`
* [getCraftTableByMarker](#getcrafttablebymarker) -> `Busca os dados de uma bancada pelo elemento marker`
## createCraftTable
**Side:** `server`
**Syntax**
```lua theme={null}
local id = exports['sqh_craftsystem']:createCraftTable(position, permissions, upgrades, configId)
```
**Required arguments**
* `position` (`table`): posição e rotação da bancada.
* `x` (`number`): coordenada X
* `y` (`number`): coordenada Y
* `z` (`number`): coordenada Z
* `rotX` (`number`): rotação X (padrão `0`)
* `rotY` (`number`): rotação Y (padrão `0`)
* `rotZ` (`number`): rotação Z (padrão `0`)
* `interior` (`number`): interior do jogo (padrão `0`)
* `dimension` (`number`): dimensão do jogo (padrão `0`)
**Optional arguments**
* `permissions` (`table`): lista de grupos ACL que podem usar a bancada. Exemplo: `{'Admin', 'Vip'}`. Se vazio ou `nil`, todos os players podem usar.
* `upgrades` (`table`): upgrades iniciais da bancada.
* `fuel` (`number`): combustível inicial (padrão `0`)
* `consumable_boost` (`number`): ácido clorídrico inicial (padrão `0`)
* `slot_upgrade` (`number`): slots de fabricação iniciais (padrão `1`)
* `parallel_upgrade` (`number`): fabricações paralelas iniciais (padrão `1`)
* `primary_part_1` a `primary_part_4` (`number`): nível inicial das peças primárias (padrão `1`)
* `configId` (`string`): ID fixo para identificar a bancada entre restarts. Recomendado para bancadas default.
**Return**
* `number` com o ID da bancada criada em sucesso.
* `false` em falha.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('criarbanccada', function(player, cmd)
local px, py, pz = getElementPosition(player)
local id = exports['sqh_craftsystem']:createCraftTable(
{ x = px, y = py, z = pz, rotZ = 0 },
{ 'Admin' },
{ fuel = 50, slot_upgrade = 2 },
'bancada_centro'
)
if id then
outputChatBox('Bancada criada com ID: ' .. id, player, 0, 255, 0)
else
outputChatBox('Falha ao criar bancada', player, 255, 0, 0)
end
end)
```
## deleteCraftTable
**Side:** `server`
**Syntax**
```lua theme={null}
local success, reason = exports['sqh_craftsystem']:deleteCraftTable(id)
```
**Required arguments**
* `id` (`number`): ID da bancada a deletar.
**Return**
* `true` em sucesso.
* `false, string` em falha (bancada não encontrada ou tipo inválido).
**Observação**
* Apenas bancadas do tipo `'default'` podem ser deletadas por este export. Bancadas de player são gerenciadas pelo próprio sistema.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('deletarbancada', function(player, cmd, id)
if not id then
outputChatBox('Use: /deletarbancada ', player)
return
end
local success, reason = exports['sqh_craftsystem']:deleteCraftTable(tonumber(id))
outputChatBox(success and 'Bancada deletada' or ('Erro: ' .. tostring(reason)), player)
end)
```
## addCraftTableUpgrade
**Side:** `server`
**Syntax**
```lua theme={null}
local success, reason = exports['sqh_craftsystem']:addCraftTableUpgrade(craftTableId, upgrade, value)
```
**Required arguments**
* `craftTableId` (`number`): ID da bancada.
* `upgrade` (`string`): nome do upgrade. Valores aceitos:
* `'fuel'` — combustível
* `'consumable_boost'` — ácido clorídrico (boost consumível)
* `'slot_upgrade'` — slots de fabricação
* `'parallel_upgrade'` — fabricações simultâneas
* `'primary_part_1'` a `'primary_part_4'` — nível das peças primárias
* `value` (`number`): novo valor do upgrade. Será limitado automaticamente ao `min`/`max` configurado em `Config.upgradeSettings`.
**Return**
* `true` em sucesso.
* `false, string` em falha.
**Example**
```lua theme={null}
-- SERVER-SIDE — Abastecer uma bancada com 80 de combustível
exports['sqh_craftsystem']:addCraftTableUpgrade(1, 'fuel', 80)
-- Desbloquear 3 slots de fabricação
exports['sqh_craftsystem']:addCraftTableUpgrade(1, 'slot_upgrade', 3)
-- Adicionar ácido clorídrico (boost)
exports['sqh_craftsystem']:addCraftTableUpgrade(1, 'consumable_boost', 10)
```
## forceCraftTableSpawn
**Side:** `server`
**Syntax**
```lua theme={null}
local success, reason = exports['sqh_craftsystem']:forceCraftTableSpawn(id)
```
**Required arguments**
* `id` (`number`): ID da bancada a spawnar.
**Return**
* `true` em sucesso.
* `false, string` em falha (bancada não encontrada ou já spawnada).
**Observação**
* Força o spawn na posição salva no banco de dados, sem exigir confirmação do player. Ideal para bancadas do tipo `'default'`.
**Example**
```lua theme={null}
-- SERVER-SIDE
addEventHandler('onResourceStart', resourceRoot, function()
-- Força spawn de uma bancada default ao iniciar o resource
local success = exports['sqh_craftsystem']:forceCraftTableSpawn(1)
if not success then
outputDebugString('[CraftSystem] Falha ao spawnar bancada 1')
end
end)
```
## spawnCraftTableWithPreview
**Side:** `server`
**Syntax**
```lua theme={null}
local success = exports['sqh_craftsystem']:spawnCraftTableWithPreview(id, player)
```
**Required arguments**
* `id` (`number`): ID da bancada.
* `player` (`player`): player que receberá o modo preview para posicionar a bancada.
**Return**
* `true` se o modo preview foi iniciado com sucesso.
* `false` se falhou (bancada não encontrada, player não é o dono, ou bancada já está spawnada).
**Comportamento**
* Se a bancada já estiver spawnada, o sistema marca a posição dela no mapa do player e retorna `false`.
* Se o preview for cancelado pelo player, a bancada é automaticamente deletada.
* Ao confirmar, a bancada é spawnada na posição escolhida.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('posicionarbancada', function(player, cmd, id)
if not id then
outputChatBox('Use: /posicionarbancada ', player)
return
end
local success = exports['sqh_craftsystem']:spawnCraftTableWithPreview(tonumber(id), player)
if not success then
outputChatBox('Não foi possível iniciar o posicionamento', player, 255, 150, 0)
end
end)
```
## spawnWithPreview
**Side:** `server`
**Syntax**
```lua theme={null}
local success = exports['sqh_craftsystem']:spawnWithPreview(id, player)
```
Alias direto de [spawnCraftTableWithPreview](#spawncrafttablewithpreview). Mesmos parâmetros, retorno e comportamento.
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_craftsystem']:spawnWithPreview(craftTableId, player)
```
## spawnWithPreviewByOwner
**Side:** `server`
**Syntax**
```lua theme={null}
local success = exports['sqh_craftsystem']:spawnWithPreviewByOwner(player)
```
**Required arguments**
* `player` (`player`): player cuja bancada será buscada e iniciará o preview.
**Return**
* `true` se o preview foi iniciado.
* `false` se o player não possui bancada, ou se ela já está spawnada (nesse caso marca no mapa).
**Observação**
* Busca automaticamente a bancada do tipo `'player'` que pertence ao owner com o mesmo nome do player.
* Útil para sistemas onde o player recebe a bancada como item e precisa posicioná-la sem saber o ID.
**Example**
```lua theme={null}
-- SERVER-SIDE — Chamado quando player usa um item de bancada no inventário
addEvent('inventory:usarBancada', true)
addEventHandler('inventory:usarBancada', root, function()
local player = client
exports['sqh_craftsystem']:spawnWithPreviewByOwner(player)
end)
```
## getSpawnedCraftTables
**Side:** `server`
**Syntax**
```lua theme={null}
local tables = exports['sqh_craftsystem']:getSpawnedCraftTables()
```
**Return**
* `table` indexada por `craftTableId` com os dados de spawn no formato:
```lua theme={null}
{
[1] = { object = element, marker = element },
[2] = { object = element, marker = element },
...
}
```
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('listarbancadas', function(player)
local tables = exports['sqh_craftsystem']:getSpawnedCraftTables()
local count = 0
for id, _ in pairs(tables) do
count = count + 1
outputChatBox('Bancada ativa: ID ' .. tostring(id), player)
end
outputChatBox('Total de bancadas spawnadas: ' .. count, player)
end)
```
## getCraftTableByObject
**Side:** `server`
**Syntax**
```lua theme={null}
local craftTable = exports['sqh_craftsystem']:getCraftTableByObject(object)
```
**Required arguments**
* `object` (`element`): elemento do tipo `object` que representa a bancada no mundo.
**Return**
* `table` com os dados da bancada em sucesso.
* `nil` se não encontrar.
**Tabela retornada**
| Campo | Tipo | Descrição |
| ------------------- | -------- | ------------------------------------ |
| `id` | `number` | ID interno da bancada |
| `type` | `string` | `'default'` ou `'player'` |
| `owner` | `string` | Nome do dono (ou vazio para default) |
| `pos_x/y/z` | `number` | Posição no mundo |
| `rot_x/y/z` | `number` | Rotação |
| `interior` | `number` | Interior |
| `dimension` | `number` | Dimensão |
| `permissions` | `string` | JSON de ACLs |
| `fuel` | `number` | Combustível atual |
| `consumable_boost` | `number` | Ácido clorídrico atual |
| `slot_upgrade` | `number` | Slots de fabricação |
| `parallel_upgrade` | `number` | Fabricações paralelas |
| `primary_part_1..4` | `number` | Nível de cada peça primária |
| `is_spawned` | `number` | `1` se spawnada, `0` se não |
**Example**
```lua theme={null}
-- SERVER-SIDE
addEventHandler('onElementClicked', root, function(button, state, player)
if button ~= 'right' or state ~= 'down' then return end
if getElementType(source) ~= 'object' then return end
local craftTable = exports['sqh_craftsystem']:getCraftTableByObject(source)
if craftTable then
outputChatBox('Bancada ID: ' .. craftTable.id .. ' | Combustível: ' .. craftTable.fuel, player)
end
end)
```
## getCraftTableByMarker
**Side:** `server`
**Syntax**
```lua theme={null}
local craftTable = exports['sqh_craftsystem']:getCraftTableByMarker(marker)
```
**Required arguments**
* `marker` (`element`): elemento do tipo `marker` associado a uma bancada.
**Return**
* `table` com os dados da bancada em sucesso (mesma estrutura de [getCraftTableByObject](#getcrafttablebyobject)).
* `nil` se não encontrar.
**Example**
```lua theme={null}
-- SERVER-SIDE
addEventHandler('onMarkerHit', root, function(hitElement, matchingDimension)
if not matchingDimension then return end
if getElementType(hitElement) ~= 'player' then return end
local craftTable = exports['sqh_craftsystem']:getCraftTableByMarker(source)
if craftTable then
outputChatBox('Você está próximo da bancada ID: ' .. craftTable.id, hitElement)
end
end)
```
## Observações
* Todas as exports exigem que o resource já tenha sido iniciado e a licença validada.
* As funções acima seguem exatamente o que está exportado no `meta.xml` do `sqh_craftsystem`.
* Upgrades têm limites definidos em `Config.upgradeSettings` — valores fora do intervalo são ajustados automaticamente.
* Bancadas do tipo `'player'` não podem ser deletadas via `deleteCraftTable`; elas são gerenciadas pelo próprio flow do sistema.
# Configurações Craft System
Source: https://docs.squashcodes.com/pt/resources/craft-system/settings
Guia completo do config/settings.lua do Craft System.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Craft System é unir flexibilidade, persistência e controle total sobre as bancadas de crafting do seu servidor.
O dono do servidor tem poder absoluto para definir quais itens existem, quanto tempo cada fabricação leva, quais upgrades estão disponíveis e como o sistema se integra com o inventário e a economia do servidor.
Com a configuração, você pode:
* Definir quais itens podem ser fabricados e seus ingredientes;
* Controlar o desgaste das peças primárias e o consumo de combustível;
* Personalizar o visual das abas, categorias e interface;
* Integrar com qualquer sistema de inventário e economia via funções de callback;
* E muito mais.
## Visão Geral
Este guia cobre **todo o arquivo** `config/settings.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você saber como adicionar itens, ingredientes e upgrades.
* Você configurar o sistema sem precisar entrar nos arquivos fonte.
## Antes de Começar
* Arquivo de configuração: `config/settings.lua`
* Arquivo de banco/licença: `config/main.lua`
* Depois de alterar a config: reinicie o resource (`restart sqh_craftsystem`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## 1) `Config.tabs`
Define as abas exibidas no topo do painel de crafting.
| Campo | Tipo | Descrição |
| ------- | -------- | ---------------------------- |
| `id` | `string` | Identificador interno da aba |
| `label` | `string` | Texto exibido na aba |
| `icon` | `string` | Caminho do ícone da aba |
Abas disponíveis por padrão:
* `craft` — Fabricar Itens
* `maintenance` — Manutenção (upgrades e melhorias da bancada)
**Exemplo:**
```lua theme={null}
Config.tabs = {
{ id = "craft", label = "FABRICAR ITENS", icon = "assets/icon_34.png" },
{ id = "maintenance", label = "MANUTENÇÃO", icon = "assets/tabler_table_filled.png" },
}
```
***
## 2) `Config.categories`
Define as categorias de filtro exibidas na aba de fabricação.
| Campo | Tipo | Descrição |
| ------- | -------- | ---------------------------------- |
| `id` | `string` | Identificador interno da categoria |
| `label` | `string` | Texto exibido no filtro |
A categoria `"all"` é obrigatória e exibe todos os itens.
Os demais IDs devem corresponder ao campo `category` de cada item em `Config.craftItems`.
**Exemplo:**
```lua theme={null}
Config.categories = {
{ id = "all", label = "Todos" },
{ id = "weapons", label = "Armamento" },
{ id = "items", label = "Itens" },
{ id = "ammo", label = "Munições" },
{ id = "tools", label = "Ferramentas" },
{ id = "medical", label = "Medicina" },
{ id = "electronics", label = "Eletrônicos" },
}
```
***
## 3) `Config.hotbar`
Configura o hotbar visual de slots de fabricação exibido na tela.
| Opção | O que muda |
| ------------- | ---------------------------------------- |
| `slots` | Número total de slots exibidos no hotbar |
| `slotSize` | Tamanho em pixels de cada slot |
| `slotSpacing` | Espaçamento entre os slots |
| `startX` | Posição X inicial do hotbar na tela |
| `startY` | Posição Y inicial do hotbar na tela |
***
## 4) `Config.toolModal`
Configura o modal de peças primárias (ferramentas da bancada).
| Opção | O que muda |
| ------------- | ---------------------------------------------- |
| `w` | Largura do modal em pixels |
| `h` | Altura do modal em pixels |
| `slotSize` | Tamanho de cada slot de ferramenta |
| `slotSpacing` | Espaçamento entre slots |
| `maxSlots` | Número máximo de slots de ferramentas exibidos |
***
## 5) `Config.refuelModal`
Configura o modal de abastecimento de combustível da bancada.
| Opção | O que muda |
| -------------- | ------------------------------------------------ |
| `w` | Largura do modal |
| `h` | Altura do modal |
| `pricePerUnit` | Preço cobrado por unidade de combustível |
| `maxTank` | Capacidade máxima do tanque |
| `getMoney` | Função chamada para verificar o saldo do player |
| `takeMoney` | Função chamada para descontar dinheiro do player |
**Exemplo de integração com economia customizada:**
```lua theme={null}
Config.refuelModal = {
pricePerUnit = 500,
maxTank = 100,
getMoney = function(player)
return exports.sqh_economy:getMoney(player)
end,
takeMoney = function(player, amount)
return exports.sqh_economy:takeMoney(player, amount)
end,
}
```
***
## 6) `Config.primaryTools`
Lista as peças primárias exibidas no tooltip de ferramentas (somente visual, para referência ao jogador).
| Campo | Tipo | Descrição |
| ------------- | -------------------- | ----------------------------------------------------- |
| `id` | `string` ou `number` | Identificador da peça |
| `name` | `string` | Nome exibido |
| `description` | `string` | Descrição exibida no tooltip |
| `icon` | `string` | Caminho do ícone |
| `itemID` | `number` | ID do item no inventário (usado para verificar posse) |
**Observação:** Para o comportamento real das peças (desgaste, nível, tipo de cobrança), use `Config.primaryParts`.
***
## 7) `Config.craftItems`
**Esta é a seção mais importante.** Define todos os itens que podem ser fabricados.
Cada item aceita:
| Campo | Tipo | Descrição |
| --------------- | -------- | --------------------------------------------------------------------- |
| `id` | `number` | ID único do item (não repita IDs) |
| `name` | `string` | Nome exibido no painel |
| `description` | `string` | Descrição exibida ao selecionar o item |
| `category` | `string` | Categoria (deve existir em `Config.categories`) |
| `levelRequired` | `number` | Nível mínimo exigido do player para fabricar |
| `price` | `number` | Valor exibido (referência visual, cobrança real é pelos ingredientes) |
| `craftTime` | `number` | Tempo de fabricação em segundos |
| `icon` | `string` | Caminho do ícone do item |
| `preview` | `string` | Caminho da imagem de preview |
| `ingredients` | `table` | Lista de ingredientes necessários |
### Campos de cada ingrediente
| Campo | Tipo | Descrição |
| ---------- | -------------------- | --------------------------------------------- |
| `id` | `number` ou `string` | ID do item no inventário (aceita nome também) |
| `name` | `string` | Nome exibido |
| `icon` | `string` | Caminho do ícone |
| `required` | `number` | Quantidade necessária |
**Exemplo de item:**
```lua theme={null}
{
id = 1,
name = "Carabina",
description = "Uma carabina compacta e precisa.",
category = "weapons",
levelRequired = 12,
price = 15000,
craftTime = 90,
icon = "assets/items/special-carbine.png",
preview = "assets/items/special-carbine_preview.png",
ingredients = {
{ id = 201, name = "Ferro fundido", icon = "assets/icon_5.png", required = 20 },
{ id = 202, name = "Aço reforçado", icon = "assets/icon_6.png", required = 10 },
{ id = 203, name = "Pólvora", icon = "assets/icon_7.png", required = 5 },
},
},
```
***
## 8) `Config.maintenanceItems`
Define os itens de manutenção disponíveis na aba de manutenção. Existem dois tipos:
### `type = "consumable"` — Item consumível (ex: Ácido Clorídrico)
| Campo | Tipo | Descrição |
| ----------------------------- | ---------- | ------------------------------------------------------ |
| `id` | `string` | ID interno do item (ex: `"item_15"`) |
| `name` | `string` | Nome exibido |
| `description` | `string` | Descrição |
| `icon` | `string` | Caminho do ícone |
| `levelRequired` | `number` | Nível mínimo para comprar |
| `uses` | `number` | Quantidade de usos fornecidos |
| `price` | `number` | Preço de compra |
| `badge` | `string` | Texto do badge exibido no card (ex: `"20 usos"`) |
| `accelerate.percentage` | `number` | Chance (%) de ativar o efeito a cada craft |
| `accelerate.craftTimePercent` | `number` | Percentual de redução no tempo de craft quando ativado |
| `effects` | `table` | Efeitos visuais exibidos no card |
| `getMoney` | `function` | Função para verificar saldo do player |
| `takeMoney` | `function` | Função para descontar dinheiro do player |
### `type = "upgrade"` — Melhoria permanente (ex: Núcleo de Processamento, Motor Extra)
| Campo | Tipo | Descrição |
| --------------- | ---------- | --------------------------------- |
| `id` | `string` | ID interno |
| `name` | `string` | Nome exibido |
| `description` | `string` | Descrição |
| `icon` | `string` | Caminho do ícone |
| `levelRequired` | `number` | Nível mínimo para comprar |
| `price` | `number` | Preço de compra |
| `badge` | `string` | Texto do badge (ex: `"Melhoria"`) |
| `effects` | `table` | Efeitos visuais exibidos no card |
| `getMoney` | `function` | Função para verificar saldo |
| `takeMoney` | `function` | Função para descontar dinheiro |
### Campos de `effects` (visual)
| Campo | Tipo | Descrição |
| ------------ | --------- | ------------------------------------------------- |
| `label` | `string` | Nome do efeito |
| `valueText` | `string` | Texto do valor (ex: `"+20%"`, `"+01"`) |
| `isProgress` | `boolean` | Se `true`, exibe barra de progresso |
| `current` | `number` | Valor atual da barra (quando `isProgress = true`) |
| `maxValue` | `number` | Valor máximo da barra |
| `color` | `string` | Cor da barra: `'success'`, `'danger'`, `'info'` |
**Itens padrão e seus efeitos:**
| Item | Efeito |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `item_15` Ácido Clorídrico | Consumível — chance de reduzir o tempo de craft. Cada compra adiciona `uses` ao `consumable_boost` da bancada. |
| `item_14` Núcleo de Processamento | Upgrade — adiciona +1 slot de fabricação (`slot_upgrade`) à bancada permanentemente. |
| `item_16` Motor Extra | Upgrade — adiciona +1 fabricação simultânea (`parallel_upgrade`) à bancada permanentemente. |
***
## 9) `Config.settings`
Configurações gerais de texto e posicionamento da interface.
| Opção | O que muda |
| ------------------- | ----------------------------------------------------------------------- |
| `tableName` | Nome exibido como dono/grupo da bancada |
| `tableTitle` | Título principal exibido no painel |
| `tableDescription` | Descrição exibida abaixo do título |
| `searchPlaceholder` | Texto de placeholder da barra de busca |
| `prefixValue` | Prefixo exibido antes dos valores monetários (ex: `"PV"` → `PV 50.000`) |
| `craftsPerPartWear` | A cada quantos crafts uma peça primária perde 1 nível |
| `renderTarget` | Posição e tamanho do render target 3D (preview do item) |
### `renderTarget`
| Campo | Descrição |
| ----- | ---------------------------------- |
| `x` | Posição X do render target na tela |
| `y` | Posição Y do render target na tela |
| `w` | Largura do render target |
| `h` | Altura do render target |
***
## 10) `Config.purchaseModal`
Configura o modal de confirmação de compra exibido na aba de manutenção.
| Opção | O que muda |
| ------------- | --------------------------- |
| `w` | Largura do modal |
| `h` | Altura do modal |
| `title` | Título do modal |
| `description` | Texto de confirmação |
| `confirmText` | Texto do botão de confirmar |
| `cancelText` | Texto do botão de cancelar |
***
## 11) `Config.craftTableSettings`
Configura o comportamento físico das bancadas no mundo do jogo.
| Opção | O que muda |
| --------------------- | --------------------------------------------------------------------------- |
| `model` | ID do modelo 3D usado para a bancada |
| `interactionKey` | Tecla para interagir com a bancada / recolher |
| `closeKey` | Tecla para fechar o painel de crafting |
| `markerSize` | Tamanho do marker invisível de colisão ao redor da bancada |
| `previewColor` | Cor do preview quando a posição é válida `{ r, g, b, a }` |
| `previewInvalidColor` | Cor do preview quando a posição é inválida `{ r, g, b, a }` |
| `mapMarkDuration` | Segundos que o marcador da bancada fica no mapa quando ela já está spawnada |
**Exemplo:**
```lua theme={null}
Config.craftTableSettings = {
model = 2116,
interactionKey = "e",
closeKey = "backspace",
markerSize = 1.5,
previewColor = { r = 100, g = 255, b = 100, a = 150 },
previewInvalidColor = { r = 255, g = 100, b = 100, a = 150 },
mapMarkDuration = 10,
}
```
***
## 12) `Config.primaryParts`
Define as peças primárias que a bancada precisa para funcionar. São 4 peças (slots fixos). Cada peça possui um campo `dbField` que define onde o nível é salvo no banco.
| Campo | Tipo | Descrição |
| -------------------------- | -------------------- | ------------------------------------------------------------ |
| `dbField` | `string` | Campo no banco: `primary_part_1` a `primary_part_4` |
| `id` | `string` ou `number` | Identificador da peça |
| `name` | `string` | Nome exibido |
| `description` | `string` | Descrição |
| `icon` | `string` | Caminho do ícone |
| `takeType` | `string` | `'item'` ou `'money'` — como o player paga ao inserir a peça |
| `moneyPrice` | `number` | Preço em dinheiro (somente se `takeType = 'money'`) |
| `moneyFunctions.getMoney` | `function` | Função para obter o saldo do player |
| `moneyFunctions.takeMoney` | `function` | Função para descontar do player |
| `itemID` | `number` | ID do item no inventário (somente se `takeType = 'item'`) |
| `minLevel` | `number` | Nível mínimo da peça (normalmente `1`) |
| `maxLevel` | `number` | Nível máximo que a peça pode atingir |
**Como funciona o desgaste:**
A cada `Config.settings.craftsPerPartWear` fabricações, o sistema reduz o nível de uma peça primária em 1. Se qualquer peça chegar ao nível 0, a bancada para de funcionar até que o player insira novamente a peça.
**Exemplo de peça cobrada por item:**
```lua theme={null}
{
dbField = "primary_part_1",
id = "Broca",
name = "Broca",
takeType = 'item',
itemID = 10,
minLevel = 1,
maxLevel = 6,
}
```
**Exemplo de peça cobrada por dinheiro:**
```lua theme={null}
{
dbField = "primary_part_2",
id = 102,
name = "Esquemas",
takeType = 'money',
moneyPrice = 1000,
moneyFunctions = {
getMoney = function(player) return getPlayerMoney(player) end,
takeMoney = function(player, amount) return takePlayerMoney(player, amount) end,
},
minLevel = 1,
maxLevel = 6,
}
```
***
## 13) `Config.upgradeSettings`
Define os limites mínimo, máximo e valor padrão de cada upgrade da bancada.
| Upgrade | Min | Max | Default | Descrição |
| ------------------ | --- | ----- | ------- | -------------------------------- |
| `fuel` | `0` | `100` | `0` | Combustível da bancada |
| `consumable_boost` | `0` | `20` | `0` | Ácido clorídrico acumulado |
| `slot_upgrade` | `1` | `14` | `1` | Slots de fabricação simultâneos |
| `parallel_upgrade` | `1` | `14` | `1` | Fabricações paralelas permitidas |
Valores fora do intervalo são automaticamente ajustados pelo sistema.
***
## 14) `Config.permissions`
Controla quem pode criar e gerenciar bancadas no jogo.
| Opção | O que controla |
| ------------ | ------------------------------------------------------------------------------------ |
| `create` | Lista de grupos ACL autorizados a usar `/createcrafttable` |
| `management` | Lista de grupos ACL com acesso ao painel de gerenciamento (botão direito na bancada) |
**Exemplo:**
```lua theme={null}
Config.permissions = {
create = { 'Console', 'Admin' },
management = { 'Console', 'Admin', 'Moderador' },
}
```
***
## 15) `Config.events`
**Esta seção conecta o Craft System ao inventário e economia do seu servidor.** Todas as funções devem ser substituídas pelas chamadas do seu sistema.
| Função | Quando é chamada | O que deve retornar |
| -------------------------------------------------- | ------------------------------------------------- | ---------------------------- |
| `hasItemPlayer(player, itemID)` | Ao verificar se o player possui um item | `true` ou `false` |
| `getHasQuantityItemPlayer(player, itemID, amount)` | Ao verificar a quantidade de um ingrediente | `number` (quantidade atual) |
| `giveItemPlayer(player, itemID, amount)` | Ao entregar o item fabricado ao player | `true` ou `false` |
| `takeItemPlayer(player, itemID, amount)` | Ao consumir ingredientes do inventário | `true` ou `false` |
| `getPlayerIdentifier(player)` | Para identificar o player nas verificações de ACL | `string` (nome da conta MTA) |
**Exemplo de integração com sqh\_inventory:**
```lua theme={null}
Config.events = {
hasItemPlayer = function(player, itemID)
return exports.sqh_inventory:hasItem(player, itemID)
end,
getHasQuantityItemPlayer = function(player, itemID, amount)
return exports.sqh_inventory:getHasQuantityItem(player, itemID, amount)
end,
giveItemPlayer = function(player, itemID, amount)
return exports.sqh_inventory:giveItem(player, itemID, amount)
end,
takeItemPlayer = function(player, itemID, amount)
return exports.sqh_inventory:takeItem(player, itemID, amount)
end,
getPlayerIdentifier = function(player)
return getAccountName(getPlayerAccount(player))
end,
}
```
***
## 16) `Config.colors`
Personaliza todas as cores da interface. Cada cor usa a função `tocolor(r, g, b, a)`.
| Chave | Uso |
| ----------------------------------------------------------- | -------------------------------- |
| `primary` | Cor de destaque principal (roxo) |
| `primaryDark` | Variante escura do destaque |
| `primaryBorder` | Borda com cor de destaque |
| `textWhite` / `textWhite80` / `textWhite60` / `textWhite50` | Textos com diferentes opacidades |
| `textDark` | Texto sobre fundo claro |
| `success` / `successBg` | Verde (progresso, sucesso) |
| `danger` / `dangerAlt` / `dangerBg` | Vermelho (erro, item em falta) |
| `info` / `infoBg` | Azul (informações neutras) |
| `bgDark` / `bgLight` / `bgLighter` / `bgProgress` | Fundos do painel |
| `borderLight` / `borderLighter` / `borderDivider` | Bordas e divisores |
| `lineWhite` / `lineGray` | Linhas decorativas |
| `locked` | Slots bloqueados |
| `btnBuy` | Botão de compra |
***
## 17) `Config.fonts`
Define as fontes usadas na interface. Os valores são os nomes internos das fontes carregadas via `meta.xml`.
| Chave | Fonte carregada |
| --------------------------- | ----------------------- |
| `jetbrains_mono_medium` | JetBrainsMono-Medium |
| `jetbrains_mono_bold` | JetBrainsMono-Bold |
| `jetbrains_mono_extrabold` | JetBrainsMono-ExtraBold |
| `jetbrains_mono_regular` | JetBrainsMono-Medium |
| `roboto_condensed_regular` | RobotoCondensed-Regular |
| `roboto_condensed_medium` | RobotoCondensed-Medium |
| `roboto_condensed_bold` | RobotoCondensed-Medium |
| `tt_lakes_neue_trl_cnd_xbd` | TTExtraBold |
| `tt_lakes_neue_trl_cnd_db` | TTDemiBold |
| `tt_lakes_neue_trl_cnd_md` | TTDemiBold |
Não é necessário alterar esta seção a menos que você substitua os arquivos de fonte nas `assets/fonts/`.
***
## Boas Práticas
* Altere uma seção por vez e teste no jogo.
* IDs de `Config.craftItems` devem ser únicos — nunca repita o mesmo ID.
* A categoria de cada item em `Config.craftItems` deve existir em `Config.categories`.
* Em `Config.events`, nunca deixe as funções retornando valores fixos em produção — integre com seu inventário.
* Para adicionar um novo item de manutenção, crie uma entrada em `Config.maintenanceItems` com um ID único e ajuste as funções `getMoney`/`takeMoney`.
* Depois de salvar: `restart sqh_craftsystem`
# Custom Characters
Source: https://docs.squashcodes.com/pt/resources/custom-characters
Adquiriu o resource de customização de personagens e está com dúvidas do sistema? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no custom? Clique aqui
## Funções exportadas
* [changeClothesElement](#changeClothesElement) --> `Altera/seta/remove a roupa de um jogador`
* [setSkinTone](#setSkinTone) --> `Altera o tom de pele de um jogador`
* [getPlayerGender](#getPlayerGender) --> `Retorna o gênero de um jogador`
* [takeClothesPlayer](#takeClothesPlayer) --> `Retira todas as roupas do jogador (somente do corpo, não retira da DB!)`
* [updateTypeSelected](#updateTypeSelected) --> `Troca o tipo de roupas escolhida entre corp ou roupas normais`
* [resetCharacter](#resetCharacter) --> `Reseta a conta de um jogador para ele criar um novo personagem`
* [loadClothesElement](#loadClothesElement) --> `Carrega todas as roupas do jogador`
* [showCreatePerson](#showCreatePerson) --> `Carrega as roupas caso o jogador já tenha criado um personagem, se não, carrega o painel de criação`
* [getAccountClothes](#getAccountClothes) --> `Retorna as roupas de uma conta`
* [getPlayerClothes](#getPlayerClothes) --> `Retorna as roupas do jogador`
* [setClothesPed](#setClothesPed) --> `Define roupas para um ped`
* [setSkintonePed](#setSkintonePed) --> `Define o tom de pele de um ped`
## changeClothesElement
**Syntax**
```lua theme={null}
exports['sqh_custom']:changeClothesElement('ped' theElement, 'element or table' forPlayer, 'table' infos)
```
**Required arguments**
* ***theElement:*** Elemento que você irá setar a roupa (player)
* ***forPlayer:*** Quem irá ver as roupas desse elemento
* ***table:*** Uma tabela que necessita dos seguintes índices:
* **typeModel:** O tipo de roupa que você está mudando ('corp' ou 'default')
* **bodyPart:** A parte do corpo que a roupa irá ser colocada ('torso', 'legs', 'head', 'feet'...)
* **clotheType** O tipo da roupa que será colocada, ('camisa.padrao')
* **clotheTexture** A textura da roupa que será colocada, ('1.png')
* **gender** O gênero do jogador, ('male' or 'female')
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador definir uma roupa nele mesmo
```lua theme={null}
addCommandHandler( 'clothe', -- Exemplo: /clothe default torso camisa.padrao 10.png male
function(player, _, typeModel, bodyPart, clotheType, clotheTexture,gender)
if (typeModel and bodyPart and clotheType and clotheTexture and gender) then
exports['sqh_custom']:changeClothesElement(player, player, {typeModel = typeModel, bodyPart = bodyPart, clotheType = clotheType, clotheTexture = clotheTexture, gender = gender})
outputChatBox('Roupa colocada com sucesso!', player, 136, 201, 115)
else
outputChatBox('Não foi possível adicionar a roupa! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## setSkinTone
**Syntax**
```lua theme={null}
exports['sqh_custom']:setSkinTone('table' infos)
```
**Required arguments**
* ***table:*** Uma tabela que necessita dos seguintes índices:
* **player:** O jogador que você irá mudar o tom de pele
* **texture** A textura do tom de pele que será colocado, ('whi.png')
* **gender** O gênero do jogador, ('male' or 'female')
**Example**
```css theme={null}
[CLIENT-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador definir um tom de pele nele mesmo
```lua theme={null}
addCommandHandler( 'skintone', -- Exemplo: /skintone whi male
function(_, texture, gender)
if (texture and gender) then
exports['sqh_custom']:setSkinTone({texture = texture, gender = gender, player = localPlayer})
outputChatBox('Tom de pele colocado com sucesso!', 136, 201, 115)
else
outputChatBox('Não foi possível trocar o tom de pele! (parâmetro incorreto)', 201, 73, 73)
end
end
)
```
## getPlayerGender
**Syntax**
```lua theme={null}
exports['sqh_custom']:getPlayerGender('ped' theElement)
```
**Required arguments**
* ***theElement:*** O jogador que você quer obter o gênero
**Returns**
* Retorna o gênero do jogador caso o jogador já tenha um personagem, caso contrário irá retornar false
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que permite o jogador possa ver seu próprio gênero
```lua theme={null}
addCommandHandler( 'gender', -- Exemplo: /gender
function(player, _)
if (player) then
local genderPlayer = exports['sqh_custom']:getPlayerGender(player)
outputChatBox('Seu gênero é: '..genderPlayer, player, 136, 201, 115)
else
outputChatBox('Não foi possível retornar seu gênero! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## takeClothesPlayer
**Syntax**
```lua theme={null}
exports['sqh_custom']:takeClothesPlayer('ped' theElement, 'string' gender)
```
**Required arguments**
* ***theElement:*** O jogador que você quer retirar as roupas
* ***gender:*** O gênero do jogador
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que retira as próprias roupas
```lua theme={null}
addCommandHandler( 'takeclothes', -- Exemplo: /takeclothes male
function(player, _, gender)
if (player and gender) then
exports['sqh_custom']:takeClothesPlayer(player, gender)
outputChatBox('Você retirou suas roupas!', player, 136, 201, 115)
else
outputChatBox('Não foi possível retirar suas roupas! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## updateTypeSelected
**Syntax**
```lua theme={null}
exports['sqh_custom']:updateTypeSelected('ped' theElement, 'string' typeSelect, skinUpdate)
```
**Required arguments**
* ***theElement:*** O jogador que você quer atualizar o tipo de roupa
* ***typeSelect:*** O tipo para qual você quer mudar as roupas do player ('corp' ou 'default')
**Optional arguments**
* ***skinUpdate:*** O id da skin que deverá ser definido na database
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que troca as roupas do jogador para as roupas de corp
```lua theme={null}
addCommandHandler( 'update', -- Exemplo: /update corp
function(player, _, typeUpdate)
if (player and typeUpdate) then
exports['sqh_custom']:updateTypeSelected(player, typeUpdate)
outputChatBox('Você atualizou o tipo para: '..typeUpdate, player, 136, 201, 115)
else
outputChatBox('Não foi possível atualizar! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## resetCharacter
**Syntax**
```lua theme={null}
exports['sqh_custom']:resetCharacter('ped' theElement)
```
**Required arguments**
* ***theElement:*** O jogador que você quer resetar a conta
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que reseta a conta do jogador
```lua theme={null}
addCommandHandler( 'reset', -- Exemplo: /reset
function(player, _)
if (player) then
exports['sqh_custom']:resetCharacter(player)
outputChatBox('Você resetou sua conta', player, 136, 201, 115)
else
outputChatBox('Não foi possível resetar! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## showCreatePerson
**Syntax**
```lua theme={null}
exports['sqh_custom']:showCreatePerson('ped' theElement)
```
**Required arguments**
* ***theElement:*** O jogador que você quer abrir o painel de criação ou carregar o personagem
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que irá abrir o painel de criação ou carregar as roupas caso já tenha criado
```lua theme={null}
addCommandHandler( 'showcreate', -- Exemplo: /showcreate
function(player, _)
if (player) then
exports['sqh_custom']:showCreatePerson(player)
outputChatBox('Você chamou o create', player, 136, 201, 115)
else
outputChatBox('Não foi possível chamar a função! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## loadClothesElement
**Syntax**
```lua theme={null}
exports['sqh_custom']:showCreatePerson('ped' theElement, 'element or table' forPlayer, forceTypeModel)
```
**Required arguments**
* ***theElement:*** O jogador que você quer carregar as roupas
* ***forPlayer:*** O jogador que irá ver as roupas do player que está sendo carregado
**Optional arguments**
* ***forceTypeModel:*** Caso você queira carregar uma roupa especifica como de ('corp' ou 'default')
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que irá carregar minhas roupas para mim mesmo
```lua theme={null}
addCommandHandler( 'loadclothes', -- Exemplo: /loadclothes
function(player, _)
if (player) then
exports['sqh_custom']:loadClothesElement(player, player)
outputChatBox('Você carregou as roupas do player', player, 136, 201, 115)
else
outputChatBox('Não foi possível chamar a função! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## getPlayerClothes
**Syntax**
```lua theme={null}
exports['sqh_custom']:getPlayerClothes('player' theElement, 'string' typeClothes)
```
**Required arguments**
* ***theElement:*** O jogador que você quer retornar as roupas
**Optional arguments**
* ***typeClothes:*** Caso você queira retornar uma roupa especifica como de ('corp', 'default', 'tattos' ou 'faceshared')
**Returns**
* Retorna uma tabela contendo as roupas do jogador
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que irá retornar as roupas do jogador no debugscript
```lua theme={null}
addCommandHandler( 'retornarroupas', -- Exemplo: /retornarroupas
function(player, _)
if (player) then
local roupas = exports['sqh_custom']:getPlayerClothes(player, 'default')
iprint(roupas)
else
outputChatBox('Não foi possível chamar a função! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## getAccountClothes
**Syntax**
```lua theme={null}
exports['sqh_custom']:getAccountClothes('account' string, 'string' typeClothes)
```
**Required arguments**
* ***account:*** A conta que você deseja retornar as roupas
**Optional arguments**
* ***typeClothes:*** Caso você queira retornar uma roupa especifica como de ('corp', 'default', 'tattos' ou 'faceshared')
**Returns**
* Retorna uma tabela contendo as roupas do jogador
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que irá retornar as roupas do jogador no debugscript
```lua theme={null}
addCommandHandler( 'retornarroupas', -- Exemplo: /retornarroupas Joao
function(player, _, account)
if (player) then
local roupas = exports['sqh_custom']:getAccountClothes(account, 'default')
iprint(roupas)
else
outputChatBox('Não foi possível chamar a função! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## setClothesPed
**Syntax**
```lua theme={null}
exports['sqh_custom']:setClothesPed('ped' theElement, 'element or table' forPlayer, 'table' typeClothes)
```
**Required arguments**
* ***theElement:*** Elemento que você irá setar a roupa (ped)
* ***forPlayer:*** O elemento 'player' que irá visualizar as roupas do ped
* ***typeClothes:*** Uma tabela que necessita dos seguintes índices:
* **typeModel:** O tipo de roupa que você está mudando ('corp' ou 'default')
* **bodyPart:** A parte do corpo que a roupa irá ser colocada ('torso', 'legs', 'head', 'feet'...)
* **clotheType** O tipo da roupa que será colocada, ('camisa.padrao')
* **clotheTexture** A textura da roupa que será colocada, ('1.png')
* **gender** O gênero do jogador, ('male' or 'female')
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que irá criar um ped e setar uma bermuda nele
```lua theme={null}
addCommandHandler( 'criarped', -- Exemplo: /criarped
function(player, _)
if (player) then
local x, y, z = getElementPosition(player)
local ped = createPed(1, x, y, z)
exports['sqh_custom']:setClothesPed(ped, player, {typeModel = "default", bodyPart = "legs", clotheType = "pati.bermuda", clotheTexture = "1.png", gender = "male"})
else
outputChatBox('Não foi possível chamar a função! (parâmetro incorreto)', player, 201, 73, 73)
end
end
)
```
## setSkintonePed
**Syntax**
```lua theme={null}
exports['sqh_custom']:setSkintonePed('ped' theElement, 'element or table' forPlayer, 'table' infos)
```
**Required arguments**
* ***theElement:*** O elemento 'ped' que irá receber o tom de pele
* ***forPlayer:*** O elemento 'player' que irá visualizar as roupas do ped
* ***table:*** Uma tabela que necessita dos seguintes índices:
* **texture** A textura do tom de pele que será colocado, ('whi.png')
* **gender** O gênero do ped, ('male' or 'female')
**Example**
```css theme={null}
[SERVER-SIDE]
```
O exemplo abaixo cria um comando que cria um elemento ped e altera o tom de pele dele
```lua theme={null}
addCommandHandler( 'criarped', -- Exemplo: /criarped whi male
function(player, _, texture, gender)
if (texture and gender) then
local x, y, z = getElementPosition(player)
local ped = createPed(1, x, y, z)
exports['sqh_custom']:setSkintonePed(ped, player, {texture = texture, gender = gender})
outputChatBox('Tom de pele colocado com sucesso!', 136, 201, 115)
else
outputChatBox('Não foi possível trocar o tom de pele! (parâmetro incorreto)', 201, 73, 73)
end
end
)
```
# Como configurar o resource?
# Exports Groups System
Source: https://docs.squashcodes.com/pt/resources/group-system/exports
Adquiriu o Groups System e está com dúvidas sobre as funções exportáveis? Você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
O Groups System é um sistema completo de gestão de grupos/organizações para servidores MTA:SA.
Com ele, jogadores podem criar grupos, convidar membros, gerenciar cargos, finanças, calendário de eventos, chat interno, registros de ponto e muito mais — tudo por uma interface visual intuitiva.
Com as funções exportadas, você pode:
* Consultar grupos cadastrados e suas informações;
* Manipular o saldo de um grupo (adicionar, definir ou remover);
* Criar e deletar eventos no calendário do grupo;
* Gerenciar membros: adicionar, remover e alterar cargo;
* Alterar permissões de um cargo dentro do grupo;
* Criar e remover convites;
* Verificar se um jogador possui determinada permissão;
* Pagar e coletar salários;
* Obter a foto de perfil escolhida pelo jogador;
* E integrar essas funcionalidades em qualquer outro sistema do seu servidor.
## Funções Exportadas
### Server-side
* [getGroups](#getgroups) -> `Retorna todos os grupos cadastrados`
* [getGroupInfo](#getgroupinfo) -> `Retorna as informações de um grupo específico`
* [getPlayerGroups](#getplayergroups) -> `Retorna os grupos em que um jogador está`
* [getOfficePlayer](#getofficeplayer) -> `Retorna o cargo de um jogador em um grupo`
* [getPlayerProfilePhoto](#getplayerprofilephoto) -> `Retorna a foto de perfil escolhida pelo jogador`
* [addGroupBalance](#addgroupbalance) -> `Adiciona saldo ao grupo`
* [setGroupBalance](#setgroupbalance) -> `Define o saldo do grupo`
* [removeGroupBalance](#removegroupbalance) -> `Remove saldo do grupo`
* [createGroupEvent](#creategroupevent) -> `Cria um evento no calendário do grupo`
* [deleteGroupEvent](#deletegroupevent) -> `Deleta um evento do calendário`
* [setPlayerRoleInGroup](#setplayerrole-ingroup) -> `Altera o cargo de um membro`
* [changeGroupPermissionRole](#changegrouppermissionrole) -> `Altera uma permissão de um cargo`
* [createInvite](#createinvite) -> `Envia um convite para um jogador`
* [removeInvite](#removeinvite) -> `Remove um convite pendente`
* [addPlayerToGroup](#addplayertogroup) -> `Adiciona um jogador diretamente a um grupo`
* [removePlayerFromGroup](#removeplayerfromgroup) -> `Remove um jogador de um grupo`
* [editGroupInfo](#editgroupinfo) -> `Edita informações gerais do grupo`
* [playerHasPermission](#playerhaspermission) -> `Verifica se um jogador tem uma permissão no grupo`
* [verifyGroup](#verifygroup) -> `Marca/desmarca um grupo como verificado (oficial)`
* [deleteGroup](#deletegroup) -> `Deleta um grupo permanentemente`
* [payGroupSalary](#paygroupsalary) -> `Paga os salários de todos os membros de um grupo`
* [collectPlayerSalary](#collectplayersalary) -> `Coleta os salários pendentes de um jogador`
* [managePanels](#managepanels) -> `Abre painéis específicos do sistema para um jogador`
***
## getGroups
**Side:** `server`
**Syntax**
```lua theme={null}
local groups = exports['sqh_groups']:getGroups()
```
**Return**
* `table` com todos os grupos cadastrados, indexados pelo `groupID` (número).
* Cada entrada contém: `nameGroup`, `members`, `events`, `balance`, `offices`, `activities`, `groupInfos`, `configurations`, `invites`.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('listargrupos', function(player)
local groups = exports['sqh_groups']:getGroups()
local count = 0
for _ in pairs(groups) do count = count + 1 end
outputChatBox('Total de grupos: ' .. count, player)
end)
```
***
## getGroupInfo
**Side:** `server`
**Syntax**
```lua theme={null}
local group = exports['sqh_groups']:getGroupInfo(groupID)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
**Return**
* `table` com todas as informações do grupo em sucesso.
* `false` se o grupo não existir.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('infogrupo', function(player, _, groupID)
local group = exports['sqh_groups']:getGroupInfo(tonumber(groupID))
if group then
outputChatBox('Grupo: ' .. group.nameGroup .. ' | Membros: ' .. #group.members, player)
else
outputChatBox('Grupo não encontrado.', player)
end
end)
```
***
## getPlayerGroups
**Side:** `server`
**Syntax**
```lua theme={null}
local groups = exports['sqh_groups']:getPlayerGroups(player)
```
**Required arguments**
* `player` (`player`): elemento do jogador.
**Return**
* `table` com a lista de grupos do jogador (`{ {groupID = X}, ... }`).
* `false` se não encontrado ou sem grupos.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('meusgrupos', function(player)
local groups = exports['sqh_groups']:getPlayerGroups(player)
if groups then
outputChatBox('Você está em ' .. #groups .. ' grupo(s).', player)
else
outputChatBox('Você não está em nenhum grupo.', player)
end
end)
```
***
## getOfficePlayer
**Side:** `server`
**Syntax**
```lua theme={null}
local office = exports['sqh_groups']:getOfficePlayer(player, groupID)
```
**Required arguments**
* `player` (`player`): elemento do jogador.
* `groupID` (`number`): ID do grupo.
**Return**
* `table` com campos:
* `officeRank` (`number`): hierarquia do cargo (número menor = cargo mais alto).
* `roleName` (`string`): nome do cargo.
* `officeID` (`number`): ID interno do cargo.
* `false` em falha.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('meucargo', function(player, _, groupID)
local office = exports['sqh_groups']:getOfficePlayer(player, tonumber(groupID))
if office then
outputChatBox('Cargo: ' .. office.roleName .. ' (hierarquia ' .. office.officeRank .. ')', player)
end
end)
```
***
## getPlayerProfilePhoto
**Side:** `server`
**Syntax**
```lua theme={null}
local photo = exports['sqh_groups']:getPlayerProfilePhoto(player)
```
**Required arguments**
* `player` (`player`): elemento do jogador.
**Return**
* Valor/índice da foto de perfil escolhida pelo jogador em sucesso.
* `false` em falha.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('fotoperfil', function(player)
local photo = exports['sqh_groups']:getPlayerProfilePhoto(player)
outputChatBox('Foto de perfil: ' .. tostring(photo), player)
end)
```
***
## addGroupBalance
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:addGroupBalance(groupID, value)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `value` (`number`): valor a ser adicionado.
**Behavior**
* Soma o valor ao saldo atual do grupo.
* Registra automaticamente a entrada no histórico financeiro do dia atual.
* Salva na database.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('depositargrupo', function(player, _, groupID, value)
exports['sqh_groups']:addGroupBalance(tonumber(groupID), tonumber(value))
outputChatBox('Depósito realizado.', player)
end)
```
***
## setGroupBalance
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:setGroupBalance(groupID, value)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `value` (`number`): novo saldo.
**Behavior**
* Define o saldo do grupo para exatamente o valor informado (sobrescreve o atual).
* Salva na database.
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_groups']:setGroupBalance(1, 50000)
```
***
## removeGroupBalance
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:removeGroupBalance(groupID, value)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `value` (`number`): valor a ser subtraído.
**Behavior**
* Subtrai o valor do saldo atual do grupo.
* Registra automaticamente a saída no histórico financeiro do dia atual.
* Salva na database.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('retirargrupo', function(player, _, groupID, value)
exports['sqh_groups']:removeGroupBalance(tonumber(groupID), tonumber(value))
outputChatBox('Retirada realizada.', player)
end)
```
***
## createGroupEvent
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:createGroupEvent(groupID, eventName, durationEvent, iconEvent, startTimestamp, monthCreation, dayCreation)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `eventName` (`string`): nome do evento.
* `durationEvent` (`number`): duração do evento (em segundos ou conforme seu padrão).
* `iconEvent` (`string`): ícone do evento.
* `startTimestamp` (`number`): timestamp Unix de início do evento (deve ser no futuro).
* `monthCreation` (`number`): número do mês em que o evento está sendo criado.
* `dayCreation` (`number`): dia do mês em que o evento está sendo criado.
**Return**
* `false` se `startTimestamp` for menor ou igual ao momento atual.
**Example**
```lua theme={null}
-- SERVER-SIDE
local futuro = os.time() + (24 * 60 * 60) -- amanhã
exports['sqh_groups']:createGroupEvent(1, 'Reunião Semanal', 3600, 'ico_work', futuro, os.date('*t').month + 1, os.date('*t').day)
```
***
## deleteGroupEvent
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:deleteGroupEvent(groupID, eventTimestamp, eventName)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `eventTimestamp` (`number`): timestamp do evento a deletar.
* `eventName` (`string`): nome do evento (usado para confirmar qual deletar quando há múltiplos no mesmo horário).
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_groups']:deleteGroupEvent(1, 1740000000, 'Reunião Semanal')
```
***
## setPlayerRoleInGroup
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:setPlayerRoleInGroup(player, groupID, roleName)
```
**Required arguments**
* `player` (`player`): elemento do jogador que terá o cargo alterado.
* `groupID` (`number`): ID do grupo.
* `roleName` (`string`): nome exato do cargo (deve existir dentro do grupo).
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('promover', function(player, _, targetName, groupID, role)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_groups']:setPlayerRoleInGroup(target, tonumber(groupID), role)
end
end)
```
***
## changeGroupPermissionRole
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:changeGroupPermissionRole(groupID, roleName, permission, status)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `roleName` (`string`): nome do cargo.
* `permission` (`string`): nome da permissão (ex: `'accessChat'`, `'manageMembers'`, `'administrator'`, etc.).
* `status` (`boolean`): `true` para ativar, `false` para desativar.
**Permissões disponíveis**
| Permissão | Descrição |
| --------------------- | ------------------------------------ |
| `accessCalendar` | Acessar o calendário |
| `accessChat` | Acessar o chat interno |
| `accessUtilities` | Acessar o painel de utilidades |
| `accessData` | Acessar dados e estatísticas |
| `accessFinancial` | Acessar o financeiro |
| `accessManager` | Acessar o gerenciador |
| `addEvents` | Criar eventos no calendário |
| `removeEvents` | Remover eventos do calendário |
| `punchCard` | Bater ponto |
| `depositBalance` | Depositar saldo |
| `withdrawBalance` | Retirar saldo |
| `paySalaries` | Pagar salários |
| `sendMessageGeneral` | Enviar mensagem para todos os cargos |
| `sendMessageByRole` | Enviar mensagem pelo cargo |
| `editGroupSettings` | Editar configurações do grupo |
| `manageMembers` | Gerenciar membros |
| `manageRoles` | Gerenciar cargos |
| `manageInvitations` | Gerenciar convites |
| `accessGroupDataLogs` | Acessar logs do grupo |
| `administrator` | Acesso total (administrador) |
| `kickMembers` | Expulsar membros |
**Example**
```lua theme={null}
-- SERVER-SIDE
-- Liberar acesso ao chat para o cargo "Membro" no grupo 1
exports['sqh_groups']:changeGroupPermissionRole(1, 'Membro', 'accessChat', true)
```
***
## createInvite
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:createInvite(playerInviter, groupID, player)
```
**Required arguments**
* `playerInviter` (`player`): jogador que está enviando o convite.
* `groupID` (`number`): ID do grupo para onde está convidando.
* `player` (`player`): jogador que está sendo convidado.
**Behavior**
* Verifica se o jogador já está no grupo ou já tem convite pendente.
* Verifica se o jogador-alvo permite receber convites.
* Registra o convite no grupo e no perfil do jogador-alvo.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('convidar', function(player, _, targetName, groupID)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_groups']:createInvite(player, tonumber(groupID), target)
end
end)
```
***
## removeInvite
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:removeInvite(groupID, player)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `player` (`player`): jogador cujo convite será removido.
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_groups']:removeInvite(1, player)
```
***
## addPlayerToGroup
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:addPlayerToGroup(groupID, player)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `player` (`player`): jogador a ser adicionado.
**Behavior**
* Adiciona o jogador ao grupo com o cargo de menor hierarquia disponível.
* Se `aclConfigurations.systemAclActive = true`, adiciona o jogador à ACL do grupo automaticamente.
* Salva o grupo no perfil do jogador.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('adicionargrupo', function(player, _, targetName, groupID)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_groups']:addPlayerToGroup(tonumber(groupID), target)
outputChatBox('Jogador adicionado ao grupo.', player)
end
end)
```
***
## removePlayerFromGroup
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:removePlayerFromGroup(groupID, player)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `player` (`player`): jogador a ser removido.
**Behavior**
* Remove o jogador da lista de membros do grupo.
* Remove o grupo do perfil do jogador.
* Se `aclConfigurations.systemAclActive = true`, remove o jogador da ACL do grupo.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('expulsargrupo', function(player, _, targetName, groupID)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_groups']:removePlayerFromGroup(tonumber(groupID), target)
outputChatBox('Jogador removido do grupo.', player)
end
end)
```
***
## editGroupInfo
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:editGroupInfo(groupID, info, value)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `info` (`string`): campo a editar.
* `value` (`any`): novo valor.
**Campos `info` disponíveis**
| Valor de `info` | Tipo de `value` | O que muda |
| -------------------- | --------------- | -------------------------------------------------- |
| `'nameGroup'` | `string` | Nome do grupo |
| `'membersLimit'` | `number` | Limite máximo de membros |
| `'descriptionGroup'` | `string` | Descrição do grupo |
| `'visibilityGroup'` | `boolean` | Visibilidade pública (`true`) ou privada (`false`) |
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_groups']:editGroupInfo(1, 'nameGroup', 'Novo Nome')
exports['sqh_groups']:editGroupInfo(1, 'membersLimit', 30)
exports['sqh_groups']:editGroupInfo(1, 'visibilityGroup', true)
```
***
## playerHasPermission
**Side:** `server`
**Syntax**
```lua theme={null}
local hasPerm = exports['sqh_groups']:playerHasPermission(player, groupID, permissionName)
```
**Required arguments**
* `player` (`player`): elemento do jogador.
* `groupID` (`number`): ID do grupo.
* `permissionName` (`string`): nome da permissão (ver tabela em [changeGroupPermissionRole](#changegrouppermissionrole)).
**Return**
* `true` se o jogador possui a permissão (ou é dono/administrador do grupo).
* `false` caso contrário.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('verificarpermissao', function(player, _, groupID, perm)
local has = exports['sqh_groups']:playerHasPermission(player, tonumber(groupID), perm)
outputChatBox(has and 'Tem permissão' or 'Não tem permissão', player)
end)
```
***
## verifyGroup
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:verifyGroup(groupID, value)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `value` (`boolean`): `true` para marcar como verificado/oficial, `false` para remover.
**Example**
```lua theme={null}
-- SERVER-SIDE
exports['sqh_groups']:verifyGroup(1, true) -- Marca o grupo 1 como oficial
exports['sqh_groups']:verifyGroup(1, false) -- Remove a verificação
```
***
## deleteGroup
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:deleteGroup(groupID)
```
**Required arguments**
* `groupID` (`number`): ID do grupo a ser deletado.
**Behavior**
* Remove o grupo de todos os perfis de membros e pendencias de convites.
* Deleta a imagem de logo do grupo (se existir).
* Remove o histórico de chat do grupo.
* Se `aclConfigurations.systemAclActive = true`, destrói a ACL do grupo.
* Remove da database permanentemente.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('deletargrupo', function(player, _, groupID)
exports['sqh_groups']:deleteGroup(tonumber(groupID))
outputChatBox('Grupo deletado.', player)
end)
```
***
## payGroupSalary
**Side:** `server`
**Syntax**
```lua theme={null}
local success, result = exports['sqh_groups']:payGroupSalary(groupID, payerElement, deductBalance)
```
**Required arguments**
* `groupID` (`number`): ID do grupo.
* `payerElement` (`player`): jogador que está realizando o pagamento (usado nos logs). Pode ser `nil` para usar o dono do grupo.
**Optional arguments**
* `deductBalance` (`boolean`): se `false`, os salários são registrados **sem descontar** o saldo do grupo. Padrão: `true`.
**Return**
* `true` em sucesso.
* `false, "insufficient_balance"` se o saldo do grupo for insuficiente.
* `false, "group_not_found"` se o grupo não existir.
* `false, "license"` se a licença for inválida.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('pagarsalarios', function(player, _, groupID)
local ok, err = exports['sqh_groups']:payGroupSalary(tonumber(groupID), player)
if ok then
outputChatBox('Salários pagos com sucesso!', player)
else
outputChatBox('Erro: ' .. tostring(err), player)
end
end)
```
```lua theme={null}
-- Registrar salários sem descontar do saldo (útil para sistemas de recompensa externa)
exports['sqh_groups']:payGroupSalary(1, nil, false)
```
***
## collectPlayerSalary
**Side:** `server`
**Syntax**
```lua theme={null}
local success, result = exports['sqh_groups']:collectPlayerSalary(playerElement, groupID)
```
**Required arguments**
* `playerElement` (`player`): jogador que irá coletar os salários.
**Optional arguments**
* `groupID` (`number`): se informado, coleta apenas os salários deste grupo. Se `nil`, coleta **todos** os pendentes.
**Return**
* `true, valorTotal` em sucesso — o valor total coletado é enviado automaticamente ao jogador conforme `widthdrawConfigurations`.
* `false, "no_pending_salary"` se não há salários pendentes.
* `false, "player_not_found"` se o jogador não estiver na database.
* `false, "license"` se a licença for inválida.
**Example**
```lua theme={null}
-- SERVER-SIDE: coletar todos os salários pendentes
addCommandHandler('coletarsalario', function(player)
local ok, value = exports['sqh_groups']:collectPlayerSalary(player)
if ok then
outputChatBox('Você coletou R$ ' .. tostring(value) .. ' em salários!', player)
else
outputChatBox('Sem salários pendentes.', player)
end
end)
```
```lua theme={null}
-- SERVER-SIDE: coletar salários apenas de um grupo específico
exports['sqh_groups']:collectPlayerSalary(player, 1)
```
***
## managePanels
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_groups']:managePanels(typeManage, groupID, tableArguments)
```
**Required arguments**
* `typeManage` (`string`): tipo de painel a abrir (ver tabela abaixo).
* `groupID` (`number`): ID do grupo (necessário em alguns tipos).
* `tableArguments` (`table`): argumentos adicionais (pode ser `nil` dependendo do tipo).
**Valores de `typeManage`**
| Valor | O que faz | `groupID` necessário? |
| ----------------------- | ------------------------------------------------ | --------------------- |
| `'openPanel'` | Abre o painel principal de grupos para o jogador | Não |
| `'openDashboardGroups'` | Abre o dashboard de um grupo específico | Sim |
| `'openFinancesGroups'` | Abre a aba financeira do grupo | Sim |
| `'openCalendarGroups'` | Abre o calendário do grupo | Sim |
| `'openChatGroups'` | Abre o chat interno do grupo | Sim |
| `'openDatasGroups'` | Abre a aba de dados/relatórios do grupo | Sim |
**Example**
```lua theme={null}
-- SERVER-SIDE: abrir o painel principal para o jogador
addCommandHandler('painel', function(player)
exports['sqh_groups']:managePanels('openPanel', nil, nil)
end)
```
```lua theme={null}
-- SERVER-SIDE: abrir o dashboard de um grupo específico
addCommandHandler('dashboard', function(player, _, groupID)
exports['sqh_groups']:managePanels('openDashboardGroups', tonumber(groupID), nil)
end)
```
***
## Observações
* Todas as exports exigem que o resource esteja ativo e com licença válida.
* As funções acima seguem exatamente o que está exportado no `meta.xml` do `sqh_groups`.
* O `source` utilizado internamente nas notificações e triggers se refere ao jogador que chamou o evento. Ao usar as exports de outros resources, certifique-se de que o contexto de `source` seja o correto.
# Configurações Groups System
Source: https://docs.squashcodes.com/pt/resources/group-system/settings
Guia completo dos arquivos config/settings.lua e config/main.lua do Groups System.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
O Groups System é um sistema completo de gestão de grupos/organizações para servidores MTA:SA.
Com ele, jogadores podem criar grupos, convidar membros, gerenciar cargos, finanças, calendário de eventos, chat interno, registros de ponto e muito mais — tudo através de uma interface visual intuitiva.
## Visão Geral
Este guia cobre **todo o arquivo** `config/settings.lua` e também o `config/main.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você saber quando usar `true` ou `false`.
* Você configurar o sistema sem precisar entrar em detalhes técnicos.
## Antes de Começar
* Arquivos de configuração: `config/settings.lua` e `config/main.lua`
* Depois de alterar a config: reinicie o resource (`restart sqh_groups`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## `config/main.lua` — Banco de Dados
O arquivo `config/main.lua` é onde você define a conexão com o banco de dados.
### `serverConfig.connect`
| Opção | O que muda |
| ---------------- | --------------------------------------------------------------------- |
| `database` | Tipo de banco de dados: `'sqlite'` ou `'mysql'` |
| `sqlite_archive` | Caminho do arquivo SQLite (usado apenas quando `database = 'sqlite'`) |
**Configuração com SQLite (padrão)**
```lua theme={null}
serverConfig = {
connect = {
database = 'sqlite',
sqlite_archive = 'assets/database/Database.db'
}
}
```
**Configuração com MySQL**
```lua theme={null}
serverConfig = {
connect = {
database = 'mysql',
mysqlparameters = {
hostname = "127.0.0.1", -- IP do servidor MySQL
username = "root", -- Usuário com permissões admin
password = "suasenha", -- Senha do usuário
database = "resources" -- Nome da database
}
}
}
```
***
## `config/settings.lua`
***
## 1) `license`
Sua licença de uso do produto.
```lua theme={null}
license = {
["Email"] = "seu@email.com",
["Key"] = "SQUASH-xxxx-xxxx",
}
```
| Campo | Descrição |
| ------- | --------------------------- |
| `Email` | E-mail cadastrado na compra |
| `Key` | Chave de licença fornecida |
***
## 2) `integrations`
Integrações opcionais com outros sistemas.
| Opção | `true` | `false` |
| -------------- | -------------------------------------------- | ----------------- |
| `sqh_accounts` | Ativa integração com o sistema sqh\_accounts | Desativa (padrão) |
***
## 3) `config.panel`
Controla como os painéis do sistema são abertos.
| Opção | O que muda |
| ---------------------------- | ----------------------------------------------------------------------------------- |
| `openType` | Como o painel principal abre: `'bind'` (tecla) ou `'command'` (comando) |
| `keyOpen` | Tecla ou nome do comando para abrir o painel principal |
| `openTypeStaff` | Como o painel staff abre: `'bind'` ou `'command'` |
| `keyOpenStaff` | Tecla ou nome do comando para abrir o painel staff |
| `permissionToOpenStaffPanel` | `true` exige permissão para abrir o painel staff |
| `permissionType` | Como verificar a permissão: `'ACL'`, `'elementData'` ou `'Function'` |
| `typeValue` | ElementData key (usado somente com `permissionType = 'elementData'`) |
| `DataValue` | Valor/ACL a ser verificado |
| `typeFunction` | Função customizada de verificação (usado somente com `permissionType = 'Function'`) |
**Exemplo: painel principal com tecla, painel staff requer ACL**
```lua theme={null}
["panel"] = {
openType = 'bind',
keyOpen = "F4",
openTypeStaff = 'bind',
keyOpenStaff = "F6",
['permissionToOpenStaffPanel'] = true,
['permissionType'] = 'ACL',
['DataValue'] = 'Console', -- grupo ACL que pode acessar o painel staff
}
```
***
## 4) `config.notify`
Define as funções de notificação do sistema. Você precisa apontar o exports de infobox/notify do seu servidor.
| Função | Side | Descrição |
| -------- | ------ | ----------------------------------------------------- |
| `server` | Server | Chamada pelo server para notificar um jogador |
| `client` | Client | Chamada pelo client para exibir uma notificação local |
```lua theme={null}
["notify"] = {
['server'] = function(source, type, message)
exports["s_infobox"]:addInsInfobox(source, message, type)
end,
['client'] = function(type, message, source)
exports["s_infobox"]:addIncInfobox(message, type)
end,
},
```
> Substitua os exports pelo sistema de notificação do seu servidor.
***
## 5) `config.avatars`
Integração com sistema de avatares. Se você não utiliza o `sqh_avatars`, pode ignorar ou deixar como está.
| Opção | Descrição |
| ------------- | ----------------------------------------------------------- |
| `resource` | Nome do resource de avatares |
| `getAvatar` | Função que retorna o caminho da imagem de um avatar pelo ID |
| `loadAvatars` | Função que retorna todos os avatares disponíveis |
***
## 6) `config.configurations`
Seção principal de configurações do sistema de grupos.
***
### 6.1) `protectedGroups`
Lista de nomes de grupos que **não podem ser criados** pelos jogadores via painel.
```lua theme={null}
['protectedGroups'] = {
'STAFF',
'Console',
},
```
> Use isso para proteger nomes de grupos reservados para uso interno do servidor.
***
### 6.2) `aclConfigurations`
Configurações do sistema de ACL automático.
| Opção | `true` | `false` |
| ----------------- | ----------------------------------------------------- | ------------------------------------- |
| `systemAclActive` | Cria uma ACL automaticamente quando um grupo é criado | Desativa a criação automática de ACLs |
**`receiveACLDefault`**
Permite que um grupo específico receba automaticamente uma ACL específica quando um membro entra.
```lua theme={null}
['receiveACLDefault'] = {
[1] = 'Policia', -- Grupo com ID 1 receberá a ACL 'Policia' ao entrar
}
```
***
### 6.3) `defaultConfigurations`
> ⚠️ **ATENÇÃO — LEIA COM ATENÇÃO:**
>
> As configurações dentro de `defaultConfigurations` são aplicadas **somente na primeira inicialização do sistema** (quando a database ainda não existe ou foi apagada). Após a criação da database, estas opções **não têm mais efeito** — as configurações passam a ser gerenciadas diretamente pelo **painel admin (tecla F6)**.
>
> Se você quiser alterar qualquer uma dessas opções depois que o sistema já foi iniciado, faça isso pelo painel staff, não por aqui.
| Opção | Tipo | Descrição |
| --------------------- | --------- | ---------------------------------------------------------- |
| `createGroupsMembers` | `boolean` | `true` permite que membros comuns criem grupos |
| `createPublicGroups` | `boolean` | `true` permite a criação de grupos públicos |
| `maxMembersLimit` | `number` | Limite máximo de membros que o líder pode definir no grupo |
| `maxDefaultMembers` | `number` | Quantidade padrão de membros ao criar um grupo |
| `maxValueSalary` | `number` | Maior salário possível para um cargo |
| `taxPercentage` | `number` | Porcentagem de imposto cobrado sobre a folha salarial |
| `limitGroupsCreate` | `number` | Quantidade máxima de grupos que uma pessoa pode criar |
| `maxGroupsJoin` | `number` | Quantidade máxima de grupos que uma pessoa pode participar |
***
### 6.4) `memberPermissionToCreateGroup`
Define como verificar se um membro tem permissão para criar grupos (utilizado somente quando `createGroupsMembers = false`).
| Opção | Descrição |
| ------------------ | ------------------------------------------------------------------------------------- |
| `typeVerification` | Método de verificação: `'elementData'`, `'ACL'` ou `'Function'` |
| `typeValue` | Chave da ElementData (usado somente com `typeVerification = 'elementData'`) |
| `DataValue` | Valor a comparar / grupo ACL a verificar |
| `typeFunction` | Função customizada de verificação (usado somente com `typeVerification = 'Function'`) |
**Exemplo com Function:**
```lua theme={null}
['memberPermissionToCreateGroup'] = {
['typeVerification'] = 'Function',
['typeFunction'] = function(playerElement)
local hasPermission = exports['sqh_permissions']:hasPermission(playerElement, 'createGroup')
return hasPermission
end,
},
```
**`paymentToCreate`** — cobrança para criar o grupo
Dentro de `memberPermissionToCreateGroup`, você pode configurar uma cobrança obrigatória para que o jogador pague um valor ao criar um grupo. Quando ativo, ao clicar em **"Criar grupo"**, um modal de confirmação é exibido com o custo. O grupo só é criado após o jogador confirmar e o valor ser descontado pelo servidor.
| Opção | Tipo | Descrição |
| -------------- | ------------------------- | ----------------------------------------------------- |
| `payToCreate` | `boolean` | `true` ativa a cobrança ao criar um grupo |
| `moneyName` | `string` | Nome da moeda/recurso exibido no modal de confirmação |
| `paymentValue` | `number` | Valor cobrado para criar o grupo |
| `verifyMoney` | `function(player)` | Função que retorna o saldo atual do jogador |
| `takeMoney` | `function(player, value)` | Função que desconta o valor do jogador |
```lua theme={null}
['memberPermissionToCreateGroup'] = {
['typeVerification'] = 'elementData',
['paymentToCreate'] = {
['payToCreate'] = true,
['moneyName'] = 'coins',
['paymentValue'] = 4000,
['verifyMoney'] = function(player)
return getPlayerMoney(player)
end,
['takeMoney'] = function(player, value)
return takePlayerMoney(player, value)
end
}
},
```
> Se `payToCreate = false`, nenhuma cobrança é feita e o modal não aparece.
***
### 6.5) `defaultRoles`
Define os cargos que serão criados automaticamente em cada novo grupo.
Cada cargo aceita:
| Campo | Descrição |
| -------------------------- | ------------------------------------------------------------------------ |
| `roleName` | Nome do cargo |
| `hierarchy` | Hierarquia: `1` = mais alto (líder), números maiores = cargos inferiores |
| `defaultPermissionsValues` | Tabela de permissões padrão do cargo ao ser criado |
```lua theme={null}
['defaultRoles'] = {
{roleName = 'Líder', hierarchy = 1, defaultPermissionsValues = {
administrator = true, -- Com administrator = true, o cargo tem acesso total
-- Todas as outras permissões podem ser false pois administrator sobrescreve
}},
{roleName = 'Membro', hierarchy = 2, defaultPermissionsValues = {
accessChat = true,
punchCard = true,
administrator = false,
}},
},
```
> A lista completa de permissões disponíveis está na seção [Permissões disponíveis](/pt/resources/groups-exports#changegrouppermissionrole) do guia de exports.
***
### 6.6) `defaultPermissionsValues`
Permissões padrão que um **novo cargo criado dentro do painel** receberá no momento da criação.
```lua theme={null}
['defaultPermissionsValues'] = {
accessCalendar = false, accessChat = false, administrator = false,
-- ... todas as permissões começam como false por padrão
},
```
***
### 6.7) Limites de caracteres e eventos
| Opção | Descrição |
| -------------------------- | ----------------------------------------------------------- |
| `maxCharactersNameProfile` | Máximo de caracteres para o nome de perfil do jogador |
| `maxCharactersGroupName` | Máximo de caracteres para o nome de um grupo |
| `maxShowEvents` | Quantidade máxima de próximos eventos exibidos na dashboard |
***
### 6.8) `widthdrawConfigurations`
Define para onde vai o valor quando um jogador retira seu salário ou deposita no cofre.
| Opção | Descrição |
| ------------------ | --------------------------------------------------------------------------------- |
| `withdrawType` | `'Account'` (dinheiro MTA) ou `'ElementData'` (dado de elemento) |
| `elementDataMoney` | Chave da ElementData onde será somado o valor (usado somente com `'ElementData'`) |
```lua theme={null}
['widthdrawConfigurations'] = {
['withdrawType'] = 'Account', -- Usa givePlayerMoney diretamente
["elementDataMoney"] = '',
},
```
***
## 7) `config.accounts`
Define como o sistema identifica e armazena a conta de cada jogador.
### Como pegar o nome do membro
| Opção | Valor | Descrição |
| -------------------- | --------------- | -------------------------------------------------------- |
| `getNameMember` | `'Account'` | Usa o nome da conta MTA |
| `getNameMember` | `'ElementData'` | Usa uma ElementData |
| `getNameMember` | `'Function'` | Usa uma função customizada |
| `getNameElementData` | `string` | Chave da ElementData do nome (usado com `'ElementData'`) |
| `getNameFunction` | `function` | Função que retorna o nome (usado com `'Function'`) |
### Como salvar a conta do jogador
| Opção | Valor | Descrição |
| ------------------ | --------------- | ----------------------------------------------------------- |
| `accountype` | `'Account'` | Usa a conta padrão do MTA |
| `accountype` | `'ElementData'` | Usa um ID por ElementData |
| `accountype` | `'Function'` | Usa uma função customizada |
| `idelementdata` | `string` | Chave da ElementData de ID (usado com `'ElementData'`) |
| `externalfunction` | `function` | Função que retorna o identificador (usado com `'Function'`) |
***
## 8) `config.colors`
Personalização completa das cores da interface.
### `colors.default`
Paleta de cores base da interface.
| Opção | Descrição |
| ------------------------------ | -------------------------------------- |
| `default` | Cor de destaque principal |
| `background_1` | Camada de fundo 1 (mais escura) |
| `background_2` | Camada de fundo 2 |
| `background_3` | Camada de fundo 3 |
| `background_create_subpanels` | Fundo dos subpainéis de criação |
| `default_element_1/2/3` | Cor de elementos por camada |
| `default_element_subpanels` | Cor de elementos nos subpainéis |
| `alternative_element_2/3` | Cores alternativas de elementos |
| `stroke_high` | Borda em destaque |
| `stroke_alternative_element_3` | Borda do elemento alternativo camada 3 |
| `stroke_default_element_3` | Borda do elemento padrão camada 3 |
| `text_default_title` | Cor dos títulos |
| `text_default_subtitle` | Cor dos subtítulos |
| `text_default_description` | Cor das descrições |
| `line_1/2/3` | Cor das linhas separadoras por camada |
> Todos os valores são strings hexadecimais **sem o `#`** (ex: `"5865F2"`).
### `colors.extra`
Cores de status e elementos especiais.
| Opção | Descrição |
| -------------------- | -------------------------------- |
| `status_green` | Cor de status positivo/online |
| `status_yellow` | Cor de status de aviso |
| `status_red` | Cor de status negativo |
| `verified_blue` | Cor do ícone de grupo verificado |
| `delete_button` | Cor do botão de deletar |
| `light_button` | Cor de botão claro |
| `event_off` | Cor de evento desativado |
| `black_card_explore` | Cor do card preto na exploração |
| `orange` | Cor laranja |
| `rank_1/2/3` | Cores de ranking 1º/2º/3º |
| `highlight` | Cor de destaque especial |
### `colors.exploreCards`
Array de cores usadas nos cards da aba "Explorar". Você pode adicionar ou remover cores conforme preferência.
```lua theme={null}
exploreCards = {"05ADCA", "73B243", "000000", "EA3C3C", ...}
```
***
## 9) `translate`
Sistema de tradução do interface.
| Opção | Descrição |
| ---------- | -------------------------------------------- |
| `language` | Código do idioma ativo (ex: `"PT"`, `"EN"`) |
| `currency` | Símbolo da moeda exibida (ex: `"R$"`, `"$"`) |
### Como adicionar um novo idioma
1. Crie uma nova chave dentro de `translate.texts` com o código do seu idioma.
2. Altere `translate.language` para o código do novo idioma.
```lua theme={null}
translate = {
["language"] = "EN",
["texts"] = {
["EN"] = {
["global"] = {
["close"] = "Close",
["back"] = "Back",
-- ...
},
-- ...
}
}
}
```
> O sistema já vem com `"PT"` (Português) e `"EN"` (English) disponíveis.
***
## Boas Práticas
* Altere uma seção por vez e teste no jogo.
* Em opções booleanas, lembre:
* `true` ativa
* `false` desativa
* Depois de salvar: `restart sqh_groups`
* **`defaultConfigurations` só tem efeito na primeira inicialização** (ou quando a database é apagada). Após isso, use o painel admin (F6) para alterar as configurações do sistema.
# Exports Multi Characters
Source: https://docs.squashcodes.com/pt/resources/multicharacters/exports
Adquiriu o Multi Characters e está com dúvidas do sistema? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Multi Characters é oferecer um sistema completo de múltiplos personagens com identidade visual, documentação (passaporte), cutscene de entrada e total integração com outros sistemas do servidor.
Com as funções exportadas, você pode:
* Abrir o painel de seleção de personagens para qualquer jogador;
* Exibir o passaporte de um jogador para outro jogador;
* Exibir o passaporte de um personagem pelo ID do banco;
* Buscar as informações do passaporte do personagem logado ou de qualquer personagem pelo ID;
* Abrir o painel de renovação de passaporte;
* Iniciar a cutscene de chegada para um jogador;
* Deletar um personagem por ID ou por nome.
## Funções Exportadas
### Server-side
* [openPanelCharacters](#openpanelcharacters) -> `Abre o painel de seleção de personagens para um jogador`
* [startCutscenePlayer](#startcutsceneplayer) -> `Inicia a cutscene de chegada para um jogador`
* [showPassport](#showpassport) -> `Exibe o passaporte do personagem logado para outro jogador`
* [showPassportFromID](#showpassportfromid) -> `Exibe o passaporte de qualquer personagem pelo ID`
* [openPassportRenew](#openpassportrenew) -> `Abre o painel de renovação de passaporte para um jogador`
* [getPlayerPassportInfos](#getplayerpassportinfos) -> `Retorna as informações do passaporte do personagem logado`
* [getPlayerPassportInfosByID](#getplayerpassportinfosbyid) -> `Retorna as informações do passaporte de um personagem pelo ID`
* [deletePerson](#deleteperson) -> `Deleta um personagem por ID ou por nome@sobrenome`
## openPanelCharacters
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:openPanelCharacters(player)
```
**Required arguments**
* `player` (`player`): jogador que terá o painel de personagens aberto.
**Comportamento**
* Cria o ped de lobby e muda a dimensão do jogador.
* Busca todos os personagens da conta principal do jogador e os envia para o client.
* Toca a música de lobby e trava os controles do jogador.
* Só abre se o jogador **não** estiver já no lobby.
* Dispara o evento `serverConfig.events.onStartCreationCharacter`.
**Return**
* Sem retorno explícito. O painel é aberto via `triggerClientEvent` se tiver sucesso.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('personagens', function(player)
exports['sqh_multicharacters']:openPanelCharacters(player)
end)
```
```lua theme={null}
-- SERVER-SIDE (abrir ao logar num sistema próprio)
addEventHandler('onPlayerLogin', root, function(_, account)
exports['sqh_multicharacters']:openPanelCharacters(source)
end)
```
## startCutscenePlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:startCutscenePlayer(player)
```
**Required arguments**
* `player` (`player`): jogador que irá assistir a cutscene de chegada.
**Comportamento**
* Só funciona se o jogador estiver com um personagem carregado (`playerLoggedInfos`).
* Coloca o jogador numa dimensão exclusiva, cria o avião e inicia a sequência de câmera.
* Ao terminar a cutscene, tira a foto do personagem, salva no banco e reposiciona o jogador.
* Dispara `serverConfig.events.onFinishCutscene` ao fim.
**Return**
* Sem retorno explícito.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('cutscene', function(player)
exports['sqh_multicharacters']:startCutscenePlayer(player)
end)
```
## showPassport
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:showPassport(fromPlayer, toPlayer)
```
**Required arguments**
* `fromPlayer` (`player`): jogador cujo passaporte será exibido (deve ter um personagem logado).
* `toPlayer` (`player`): jogador que verá o passaporte na tela.
**Comportamento**
* Busca os dados do personagem logado de `fromPlayer` no banco.
* Envia a interface de visualização de passaporte para `toPlayer`.
* Requer que `fromPlayer` tenha `playerLoggedInfos` com `personID` válido.
**Return**
* `false` se `fromPlayer` ou `toPlayer` forem inválidos, ou se o personagem não for encontrado.
* Sem retorno explícito em caso de sucesso (abre a interface via `triggerClientEvent`).
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('verpassaporte', function(player, _, targetName)
local target = getPlayerFromName(targetName)
if not target then
outputChatBox('Jogador não encontrado.', player)
return
end
exports['sqh_multicharacters']:showPassport(target, player)
end)
```
## showPassportFromID
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:showPassportFromID(characterID, toPlayer)
```
**Required arguments**
* `characterID` (`number`): ID do personagem no banco de dados.
* `toPlayer` (`player`): jogador que verá o passaporte na tela.
**Comportamento**
* Busca o personagem pelo ID, independente de ele estar logado ou não.
* Útil para sistemas de administração ou consulta de fichas.
**Return**
* `false` se `characterID` ou `toPlayer` forem inválidos, ou se o personagem não for encontrado.
* `true` em caso de sucesso.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('fichapersonagem', function(player, _, charIDStr)
local charID = tonumber(charIDStr)
if not charID then
outputChatBox('ID inválido.', player)
return
end
local ok = exports['sqh_multicharacters']:showPassportFromID(charID, player)
outputChatBox(ok and 'Ficha enviada' or 'Personagem não encontrado.', player)
end)
```
## openPassportRenew
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:openPassportRenew(player)
```
**Required arguments**
* `player` (`player`): jogador que terá o painel de renovação aberto.
**Comportamento**
* Requer que o jogador tenha um personagem logado (`playerLoggedInfos`).
* Abre a interface de renovação de passaporte, que permite editar nome, sobrenome, gênero, data de nascimento, nacionalidade e naturalidade (conforme `config.passport_renews.allowedEditions`).
* Cobra o valor definido em `config.passport_renews.price` do jogador.
**Return**
* Sem retorno explícito. A interface é aberta via `triggerClientEvent` em caso de sucesso.
**Example**
```lua theme={null}
-- SERVER-SIDE (via marker ou NPC)
addEventHandler('onMarkerHit', root, function(hitElement)
if getElementType(hitElement) == 'player' then
exports['sqh_multicharacters']:openPassportRenew(hitElement)
end
end)
```
## getPlayerPassportInfos
**Side:** `server`
**Syntax**
```lua theme={null}
local infos = exports['sqh_multicharacters']:getPlayerPassportInfos(player)
```
**Required arguments**
* `player` (`player`): jogador com personagem logado.
**Comportamento**
* Requer que o jogador tenha um personagem logado.
* Executa uma query coroutine-safe e aguarda o resultado antes de retornar.
**Return**
* `table` com os campos do passaporte em sucesso:
```lua theme={null}
{
emissor = "HVN", -- slug do servidor
number = 12, -- player_id do personagem
city = "CIDADE...",
name = "João",
surname = "Silva",
fullname = "João Silva",
gender = 1, -- 1 = masculino, 2 = feminino
birthDate = "01/01/2000",
nacionality = "Brasileiro",
naturality = "Brasília",
expeditionDate = "04/03/2026",
expirationDate = "03/04/2026",
profilePhoto = "base64...", -- nil se não houver foto
code = "J O Ã O ..." -- código do passaporte
}
```
* `false` se o personagem não for encontrado ou o jogador não estiver logado.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('minhaficha', function(player)
local infos = exports['sqh_multicharacters']:getPlayerPassportInfos(player)
if infos then
outputChatBox('Nome: ' .. infos.fullname, player)
outputChatBox('Nascimento: ' .. infos.birthDate, player)
else
outputChatBox('Nenhum personagem logado.', player)
end
end)
```
## getPlayerPassportInfosByID
**Side:** `server`
**Syntax**
```lua theme={null}
local infos = exports['sqh_multicharacters']:getPlayerPassportInfosByID(characterID)
```
**Required arguments**
* `characterID` (`number`): ID do personagem no banco de dados.
**Comportamento**
* Busca o personagem pelo ID, independente de ele estar logado.
* Útil para sistemas externos que precisam buscar dados de qualquer personagem.
* A busca é feita de forma coroutine-safe (bloqueia até obter resposta).
**Return**
* `table` com os mesmos campos de [getPlayerPassportInfos](#getplayerpassportinfos) em sucesso.
* `false` se o personagem não for encontrado ou o ID for inválido.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('fichaporid', function(player, _, charIDStr)
local charID = tonumber(charIDStr)
if not charID then return end
local infos = exports['sqh_multicharacters']:getPlayerPassportInfosByID(charID)
if infos then
outputChatBox('Personagem: ' .. infos.fullname .. ' | Nascido em: ' .. infos.birthDate, player)
else
outputChatBox('Personagem não encontrado.', player)
end
end)
```
## deletePerson
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_multicharacters']:deletePerson(personIDOrAccount)
```
**Required arguments**
* `personIDOrAccount` (`number` ou `string`):
* `number`: ID do personagem no banco de dados.
* `string`: nome e sobrenome no formato `"Nome@Sobrenome"` (usando o `nameSeparator` configurado).
**Comportamento**
* Deleta o personagem da tabela `characters` e da tabela `characters_profile`.
* Remove a conta MTA associada ao personagem.
* Caso o personagem esteja logado no momento, o jogador é expulso do servidor.
**Return**
* `true` quando a operação é iniciada com sucesso.
* `false` se `personIDOrAccount` for nulo ou a licença for inválida.
**Example**
```lua theme={null}
-- SERVER-SIDE (por ID)
addCommandHandler('deletarporid', function(player, _, idStr)
local id = tonumber(idStr)
if not id then return end
local ok = exports['sqh_multicharacters']:deletePerson(id)
outputChatBox(ok and 'Deletado.' or 'Falha.', player)
end)
```
```lua theme={null}
-- SERVER-SIDE (por nome@sobrenome)
addCommandHandler('deletarnome', function(player, _, nameArg)
-- nameArg esperado: "João@Silva"
local ok = exports['sqh_multicharacters']:deletePerson(nameArg)
outputChatBox(ok and 'Personagem deletado.' or 'Falha.', player)
end)
```
## Observações
* Todas as exports exigem que o resource já tenha sido liberado pela proteção de licença.
* As funções que operam sobre personagens logados (`showPassport`, `getPlayerPassportInfos`, `openPassportRenew`, `startCutscenePlayer`) requerem que o jogador tenha passado pela tela de seleção de personagens.
* As funções que recebem `characterID` funcionam independente do jogador estar online.
* As funções acima seguem o que está exportado no `meta.xml` do `sqh_multicharacters`.
# Configurações Multi Characters
Source: https://docs.squashcodes.com/pt/resources/multicharacters/settings
Guia completo dos arquivos config/main.lua e config/settings.lua do Multi Characters.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Multi Characters é oferecer um sistema completo de múltiplos personagens com identidade visual, documentação (passaporte), cutscene de entrada e total integração com outros sistemas do servidor.
## Visão Geral
Este guia cobre **todos os arquivos** `config/main.lua` e `config/settings.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você conectar o sistema ao seu servidor sem precisar mexer no código-fonte.
* Você configurar personagens, passaporte, banco de dados e integrações de forma independente.
## Antes de Começar
* Arquivos de configuração: `config/main.lua` (servidor) e `config/settings.lua` (compartilhado)
* Depois de alterar a config: reinicie o resource (`restart sqh_multicharacters`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## 1) `license`
Credenciais de ativação do produto. Localizado no topo do `config/main.lua`.
| Campo | Descrição |
| ------- | ---------------------------------------------------- |
| `Email` | E-mail da conta Squash Codes que adquiriu o produto. |
| `Key` | Chave de licença fornecida após a compra. |
```lua theme={null}
license = {
["Email"] = "seu@email.com",
["Key"] = "SQUASH-XXXX-XXXX",
}
```
***
## 2) `database`
Configuração do banco de dados. Localizado em `config/main.lua`.
| Campo | Descrição |
| -------------------------- | --------------------------------------------------- |
| `database` | Tipo de conexão: `"sqlite"` ou `"mysql"`. |
| `sqlite_archive` | Caminho do arquivo SQLite (ignorado se usar mysql). |
| `mysqlparameters.hostname` | IP ou hostname do servidor MySQL. |
| `mysqlparameters.port` | Porta do MySQL. |
| `mysqlparameters.username` | Usuário do banco. |
| `mysqlparameters.password` | Senha do banco. |
| `mysqlparameters.database` | Nome do banco de dados. |
```lua theme={null}
database = {
database = "mysql",
mysqlparameters = {
hostname = "127.0.0.1",
port = "3306",
username = "root",
password = "suasenha",
database = "nome_do_banco"
},
sqlite_archive = "assets/database/Database.db",
}
```
***
## 3) `useCustomSquash`
Define se o sistema de customização de personagens da Squash Codes será usado.
| Valor | Efeito |
| ------- | ---------------------------------------------------------------- |
| `true` | Integra com o produto `CustomSite` para skin, skintone e roupas. |
| `false` | Usa o modelo padrão definido em `setPedDefaultInfos`. |
```lua theme={null}
useCustomSquash = false
```
***
## 4) `serverConfig`
Bloco principal de configuração do servidor. Localizado em `config/main.lua`.
### `pointsElementData`
| Valor | Efeito |
| ------- | ------------------------------------------------------------------------- |
| `true` | Os pontos do jogador são lidos/escritos via `elementData`. |
| `false` | Os pontos são gerenciados de outra forma (definida em `getPointsPlayer`). |
***
### `blockChangeName`
| Valor | Efeito |
| ------- | ---------------------------------------------------------------- |
| `true` | Impede que o jogador mude seu próprio nome pelo menu ESC do MTA. |
| `false` | Permite mudança de nome pelo ESC normalmente. |
***
### `nameSeparator`
Separador entre nome e sobrenome nos comandos `/changenick` e `/deleteperson`.
```lua theme={null}
nameSeparator = "@", -- João@Silva
```
Com `"@"`, o comando fica: `/changenick João@Silva NovoNome@NovoSobrenome`
***
### `functions`
Funções de integração com o seu servidor. Você deve adaptá-las para o seu sistema.
| Função | O que faz | O que deve retornar |
| --------------------------------------------- | ---------------------------------------------------------------------------- | ------------------- |
| `getPlayerID(player)` | Retorna o ID numérico do jogador | `number` |
| `getPlayerJob(player)` | Retorna o cargo/emprego do jogador | `string` |
| `getAccountMainIdentifier(player)` | Retorna o identificador principal da conta (normalmente o nome da conta MTA) | `string` |
| `getPointsPlayer(player)` | Retorna a quantidade de pontos/coins do jogador | `number` |
| `takePointsPlayer(player, points)` | Debita pontos do jogador | qualquer |
| `getPlayerMoney(player)` | Retorna o dinheiro do jogador | `number` |
| `takePlayerMoney(player, amount)` | Debita dinheiro do jogador | qualquer |
| `getLastSkin(player)` | Retorna a última skin do jogador | `number` (model ID) |
| `setPedDefaultInfos(player, pedElement)` | Define ped do lobby quando não há personagem criado | — |
| `setPedInfos(player, pedElement, personData)` | Define ped do lobby com dados do personagem carregado | — |
**Exemplo de integração simples:**
```lua theme={null}
getPlayerJob = function(player)
return getElementData(player, "trabalho") or "Desempregado"
end,
getPointsPlayer = function(player)
return getElementData(player, "pontos") or 0
end,
takePointsPlayer = function(player, points)
setElementData(player, "pontos", (getElementData(player, "pontos") or 0) - points)
end,
```
***
### `commands`
Define os comandos administrativos disponíveis.
#### `commands.changeName`
Comando para alterar o nome de um personagem.
| Campo | Descrição |
| ------------------------- | ----------------------------------------------------------- |
| `commandName` | Nome do comando (padrão: `'changenick'`). |
| `permissionToUse(player)` | Função que retorna `true` se o jogador pode usar o comando. |
**Uso:** `/changenick Nome@Sobrenome_antigo NovoNome@NovoSobrenome`
#### `commands.deleteperson`
Comando para deletar um personagem.
| Campo | Descrição |
| ------------------------- | ----------------------------------------------------------- |
| `commandName` | Nome do comando (padrão: `'deleteperson'`). |
| `permissionToUse(player)` | Função que retorna `true` se o jogador pode usar o comando. |
**Uso:** `/deleteperson Nome@Sobrenome`
***
### `events`
Callbacks disparados em momentos específicos do ciclo de vida dos personagens.
| Evento | Quando é chamado | Parâmetros |
| ------------------------------------------------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------- |
| `onCreatePed(ped)` | Quando o ped do lobby é criado | `ped`: element do ped criado |
| `onLoginPlayer(player)` | Quando o jogador seleciona e carrega um personagem | `player` |
| `onFinishCutscene(player)` | Quando a cutscene de chegada termina | `player` |
| `onBuyPerson(player, quantityPersons)` | Quando o jogador compra um novo slot de personagem | `quantityPersons`: total de personagens após a compra |
| `onCreatePerson(player, quantityPersons, personID, actualAccount)` | Quando o jogador cria um personagem (após preencher os dados) | `personID`: ID gerado, `actualAccount`: conta MTA principal |
| `onStartCreationCharacter(player)` | Quando o painel de personagens é aberto | `player` |
**Exemplo:**
```lua theme={null}
events = {
onLoginPlayer = function(player)
setElementPosition(player, 1092, -794, 108)
triggerClientEvent(player, 'carregarHUD', player)
end,
onCreatePerson = function(player, quantityPersons, personID, actualAccount)
outputChatBox("Novo personagem criado! ID: " .. personID, player)
end,
}
```
***
## 5) `events` (settings.lua — client-side)
Callbacks de abertura e fechamento do painel. Localizado em `config/settings.lua`.
| Callback | Quando acontece | Uso típico |
| ---------------------- | --------------------------------------- | ----------------------------- |
| `onOpenPanel(player)` | Quando qualquer painel do sistema abre | Mostrar cursor, esconder chat |
| `onClosePanel(player)` | Quando qualquer painel do sistema fecha | Esconder cursor, mostrar chat |
```lua theme={null}
events = {
onOpenPanel = function(player)
showCursor(true)
showChat(false)
end,
onClosePanel = function(player)
showCursor(false)
showChat(true)
end
}
```
***
## 6) `config.infobox`
Define como as notificações do sistema são exibidas.
| Campo | Lado | Descrição |
| -------- | ------ | ------------------------------------------------ |
| `server` | Server | Função chamada para exibir infobox pelo servidor |
| `client` | Client | Função chamada para exibir infobox pelo client |
Adapte para o seu sistema de infobox:
```lua theme={null}
infobox = {
['server'] = function(source, message, type)
exports["seu_infobox"]:addServerInfobox(source, message, type)
end,
['client'] = function(source, message, type)
exports["seu_infobox"]:addClientInfobox(message, type)
end,
},
```
***
## 7) `config.logs`
Configuração dos logs de anti-cheat enviados ao Discord.
| Opção | Descrição |
| ------------- | -------------------------------------------------- |
| `enabled` | `true` ativa os logs, `false` desativa. |
| `webhookURL` | URL do webhook do Discord para receber os alertas. |
| `logLanguage` | Idioma das mensagens: `"pt"`, `"en"` ou `"es"`. |
***
## 8) Opções gerais (`config`)
Localizado em `config/settings.lua`.
| Opção | `true` / valor | `false` / efeito |
| ------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------- |
| `maxPersons` | Número máximo de personagens por jogador (ex: `7`) | — |
| `saveLastSkinPlayer` | Salva a skin do personagem ao sair para exibir no lobby | Não salva (use para Custom) |
| `keyClosePassport` | Tecla para fechar o passaporte (ex: `'backspace'`) | — |
| `openCutsceneDefault` | `true` exibe a cutscene automaticamente ao entrar | `false` desativa cutscene automática |
| `openPanelLogin` | `true` abre o painel de personagens automaticamente ao logar | `false` só abre via export |
| `namePersonWithoutAccountMain` | `true`: conta MTA = `"Nome@Sobrenome"` | `false`: conta MTA = `"ContaPrincipal@Nome_Sobrenome_"` |
| `nameSeparator` | Separador entre nome e sobrenome em toda a geração de contas (ex: `"@"`) | — |
***
## 9) `config.serverInfos`
Informações do servidor exibidas no passaporte.
| Campo | Descrição |
| ------ | -------------------------------------------------------------- |
| `name` | Nome completo do servidor. |
| `city` | Nome da cidade exibido no passaporte. |
| `slug` | Sigla/código do servidor (aparece como emissor no passaporte). |
```lua theme={null}
serverInfos = {
name = "HAVANNA ROLEPLAY",
city = "CIDADE DE HAVANNA",
slug = "HVN",
},
```
***
## 10) `config.persons_page`
Configurações da tela de seleção de personagens.
### `camera`
| Campo | Descrição |
| --------------- | --------------------------------------------------------- |
| `from` | Posição inicial da câmera `{x, y, z, lx, ly, lz}` |
| `to` | Posição final da câmera `{x, y, z, lx, ly, lz}` |
| `timeAnimation` | Tempo em segundos da animação da câmera ao entrar na tela |
### `ped`
| Campo | Descrição |
| -------------------------- | ----------------------------------------- |
| `position` | Posição do ped de lobby `{x, y, z}` |
| `rotation` | Rotação do ped `{x, y, z}` |
| `animationInfo.active` | `true` ativa animação no ped do lobby |
| `animationInfo.type` | `"random"` ou `"sequential"` |
| `animationInfo.animations` | Lista de animações: `{block, anim, time}` |
### `musics`
Lista de músicas tocadas no lobby.
Cada item aceita:
* `musicLink` (`string`): URL da música
* `name` (`string`): nome da faixa
* `author` (`string`): artista
* `album` (`string`): álbum
* `musicImage` (`string` ou `false`): URL da imagem da capa
### `persons`
Configurações dos slots de personagem.
| Campo | Descrição |
| -------------- | --------------------------------------------------------------- |
| `maxPersons` | Máximo de slots de personagem visíveis no carrossel |
| `pricePersons` | Tabela com o custo de cada slot adicional `{0, 500, 1000, ...}` |
### `notifications`
Lista de notificações exibidas na tela de lobby.
Cada notificação aceita:
* `title` (`string`): título da notificação
* `description` (`string`): corpo do texto
* `type` (`string`): tipo visual (`"info"`, `"warning"`, `"success"`, etc.)
***
## 11) `config.passport_emission`
Configurações da criação do passaporte (primeira vez que o personagem é criado).
| Opção | Descrição |
| ---------------------- | --------------------------------------------------------------------- |
| `minNameDigits` | Mínimo de caracteres para o nome |
| `maxNameDigits` | Máximo de caracteres para o nome |
| `minSurnameDigits` | Mínimo de caracteres para o sobrenome |
| `maxSurnameDigits` | Máximo de caracteres para o sobrenome |
| `minAge` | Idade mínima em anos para criar o personagem |
| `secondsAssign` | Segundos que o jogador deve segurar para assinar o documento |
| `expiresAfter` | Validade do passaporte em dias após a criação |
| `cameraPlayerPosition` | Posição da câmera para a foto do rosto: `{x, y, z, lx, ly, lz, w, h}` |
***
## 12) `config.passport_renews`
Configurações do sistema de renovação de passaporte.
| Opção | Descrição |
| ----------------- | ----------------------------------------------------------- |
| `price` | Custo em dinheiro para renovar o passaporte |
| `enableMarkers` | `true` cria markers no mapa para renovação |
| `createBlip` | `true` cria blip no mapa junto com o marker |
| `blipElementData` | `false` ou `{chave, valor}` para criar blip via elementData |
### `allowedEditions`
Define quais campos o jogador pode editar na renovação.
| Campo | `true` | `false` |
| ------------- | ----------------------------------- | ---------------------------- |
| `name` | Permite editar o nome | Bloqueia edição do nome |
| `surname` | Permite editar o sobrenome | Bloqueia edição do sobrenome |
| `birthday` | Permite editar a data de nascimento | Bloqueia edição |
| `nacionality` | Permite editar a nacionalidade | Bloqueia edição |
| `naturality` | Permite editar a naturalidade | Bloqueia edição |
| `gender` | Permite editar o gênero | Bloqueia edição |
### `markers`
Lista de posições onde aparecerão os markers de renovação.
```lua theme={null}
markers = {
{x = 1503.0, y = 1126.7, z = 9.7, type = 'cylinder', size = 3, r = 255, g = 255, b = 0},
},
```
### `peds`
Lista de peds que, ao serem clicados, abrem o painel de renovação.
```lua theme={null}
peds = {
{x = 1500.0, y = 1124.0, z = 10.0, rotation = 90, model = 56}
},
```
### `customMarkers`
Função chamada após cada marker ser criado. Use para setar elementData ou customizar o marker.
```lua theme={null}
customMarkers = function(marker)
setElementData(marker, 'custom:marker', true)
end,
```
***
## 13) `config.events` (settings.lua — server-side)
Callback disparado após a cutscene terminar no client.
| Evento | Quando é chamado |
| -------------------------- | --------------------------------------------------------- |
| `onFinishCutscene(player)` | Quando a cutscene de chegada termina no client do jogador |
```lua theme={null}
events = {
onFinishCutscene = function(player)
-- reposicionar, dar boas vindas, etc.
outputChatBox("Bem-vindo à cidade!", player)
end
}
```
***
## Boas Práticas
* Altere uma seção por vez e teste no servidor.
* As funções em `serverConfig.functions` **devem** ser adaptadas para o seu servidor — os valores padrão são apenas exemplos.
* `namePersonWithoutAccountMain` afeta diretamente o nome das contas MTA geradas. **Não mude essa opção após ter personagens já criados**, pois as contas antigas não serão renomeadas.
* Depois de salvar qualquer config: `restart sqh_multicharacters`
# Exports Phone System
Source: https://docs.squashcodes.com/pt/resources/phone-system/exports
Adquiriu o Phone System e está com dúvidas sobre as funções exportáveis? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
O Phone System é um sistema completo de celular para MTA, com aplicativos como WhatsApp, Instagram, Spotify, Paypal, Uber, Blaze e muito mais.
Com as funções exportadas, você pode:
* Dar/remover celulares para jogadores de forma programática (útil para sistemas de inventário, empregos, etc.);
* Abrir o celular para um jogador a partir de outro script;
* Buscar o número de telefone ou ID do celular por player;
* Buscar o player com base no ID ou número do celular;
* Vincular/desvincular o keybind de abrir celular manualmente;
* Gerenciar a JBL do Spotify (equipar, desequipar, dropar);
* Controlar redes Wi-Fi via script (criar, desconectar, verificar);
* Verificar/marcar contas do Instagram como verificadas.
## Funções Exportadas
### Server-side
* [buyPhone](#buyphone) -> `Dá um celular para o player`
* [openPhone](#openphone) -> `Abre o celular para um player`
* [removePhonePlayer](#removephoneplayer) -> `Remove o celular de um player`
* [getPhoneNumberByID](#getphonenumberbyid) -> `Retorna o número de telefone pelo ID do celular ou player`
* [getPhoneIDByPlayer](#getphoneIDbyplayer) -> `Retorna a lista de IDs de celulares de um player`
* [getPlayerByPhoneID](#getplayerbyphoneid) -> `Retorna o elemento player pelo ID do celular`
* [bindPhonePlayer](#bindphoneplayer) -> `Ativa o keybind de abrir celular para o player`
* [unbindPhonePlayer](#unbindphoneplayer) -> `Remove o keybind de abrir celular do player`
* [managerWifiController](#managerwificontroller) -> `Gerencia redes Wi-Fi do servidor`
* [equipSpotifyJBL](#equipspotifyjbl) -> `Equipa a JBL do Spotify no player`
* [unEquipSpotifyJBL](#unequipspotifyjbl) -> `Desequipa a JBL do Spotify do player`
* [dropSpotifyJBL](#dropspotifyjbl) -> `Dropa a JBL do Spotify no chão`
* [instagramVerifyAccount](#instagramverifyaccount) -> `Verifica ou desverifica uma conta do Instagram`
***
## buyPhone
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:buyPhone(player)
```
**Required arguments**
* `player` (`player`): jogador que receberá o celular.
**Comportamento**
* Gera um número de telefone aleatório com base no `config.system.numberType`.
* Cria o celular na database e vincula à conta do player.
* Respeita a opção `config.haveOnlyOnePhone`: se `true`, impede que o player tenha mais de um celular.
* Executa o callback `config.events.onBuyPhone(player)` após a criação.
**Return**
* Não há retorno explícito. O celular é criado na database e vinculado ao player.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('darcell', function(player)
exports['sqh_phone']:buyPhone(player)
outputChatBox('Celular dado com sucesso!', player)
end)
```
```lua theme={null}
-- SERVER-SIDE (com inventário externo)
addEventHandler('onPlayerPickUpPickup', root, function(pickup)
if pickup == phonePicup then
exports['sqh_phone']:buyPhone(source)
end
end)
```
***
## openPhone
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:openPhone(player, phoneID, configurationsOpen, forceOpen)
```
**Required arguments**
* `player` (`player`): jogador que terá o celular aberto.
**Optional arguments**
* `phoneID` (`number`): ID específico do celular a abrir. Se não informado, abre o primeiro celular da conta do player.
* `configurationsOpen` (`table`): configurações adicionais de abertura.
* `forceOpen` (`boolean`): força a abertura mesmo com restrições.
**Comportamento**
* Se o celular já tiver passado pela configuração inicial, abre na tela de bloqueio.
* Se não, inicia o fluxo de configuração inicial (setup).
* Se o player não tiver celular, envia a mensagem `translate.not_have_phone`.
**Return**
* Não há retorno explícito.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('abrircell', function(player)
exports['sqh_phone']:openPhone(player)
end)
```
```lua theme={null}
-- SERVER-SIDE (abrir celular específico)
addCommandHandler('abrircellid', function(player, _, phoneID)
exports['sqh_phone']:openPhone(player, tonumber(phoneID))
end)
```
***
## removePhonePlayer
**Side:** `server`
**Syntax**
```lua theme={null}
local success = exports['sqh_phone']:removePhonePlayer(player, phoneID)
```
**Required arguments**
* `player` (`player`): jogador que terá o celular removido.
**Optional arguments**
* `phoneID` (`number`): ID do celular a remover. Se não informado, remove o primeiro celular da conta do player.
**Return**
* `true` se o celular foi removido com sucesso.
* `false` em falha (player sem celular, ID inválido, etc.).
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('removercell', function(player)
local success = exports['sqh_phone']:removePhonePlayer(player)
outputChatBox(success and 'Celular removido!' or 'Falha ao remover celular', player)
end)
```
```lua theme={null}
-- SERVER-SIDE (remover celular específico por ID)
addCommandHandler('removercellid', function(player, _, phoneID)
local success = exports['sqh_phone']:removePhonePlayer(player, tonumber(phoneID))
outputChatBox(success and 'Celular removido!' or 'Falha ao remover celular.', player)
end)
```
***
## getPhoneNumberByID
**Side:** `server`
**Syntax**
```lua theme={null}
local number = exports['sqh_phone']:getPhoneNumberByID(player, phoneID)
```
**Required arguments**
* `player` (`player`): jogador alvo.
**Optional arguments**
* `phoneID` (`number`): ID do celular. Se não informado, busca o número do primeiro celular do player.
**Return**
* `string` com o número de telefone, ex: `"91234-5678"`.
* `false` se não encontrado.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('meunum', function(player)
local number = exports['sqh_phone']:getPhoneNumberByID(player)
outputChatBox('Seu número: ' .. tostring(number), player)
end)
```
```lua theme={null}
-- SERVER-SIDE (buscar número por ID de celular específico)
addCommandHandler('numporid', function(player, _, phoneID)
local number = exports['sqh_phone']:getPhoneNumberByID(player, tonumber(phoneID))
outputChatBox('Número do celular ' .. tostring(phoneID) .. ': ' .. tostring(number), player)
end)
```
***
## getPhoneIDByPlayer
**Side:** `server`
**Syntax**
```lua theme={null}
local phoneIDs = exports['sqh_phone']:getPhoneIDByPlayer(player)
```
**Required arguments**
* `player` (`player`): jogador alvo.
**Return**
* `table` com todos os IDs de celular vinculados ao player, ex: `{1, 5, 12}`.
* Tabela vazia `{}` se o player não tiver celular ou não estiver logado.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('meuscells', function(player)
local ids = exports['sqh_phone']:getPhoneIDByPlayer(player)
if ids and #ids > 0 then
for i, id in ipairs(ids) do
outputChatBox('Celular ' .. i .. ': ID ' .. tostring(id), player)
end
else
outputChatBox('Você não tem celular.', player)
end
end)
```
***
## getPlayerByPhoneID
**Side:** `server`
**Syntax**
```lua theme={null}
local player = exports['sqh_phone']:getPlayerByPhoneID(phoneID)
```
**Required arguments**
* `phoneID` (`number`): ID do celular.
**Return**
* `player` elemento do jogador que possui o celular, se ele estiver online.
* `false` se o celular não existir ou o dono não estiver online.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('donodocell', function(player, _, phoneID)
local owner = exports['sqh_phone']:getPlayerByPhoneID(tonumber(phoneID))
if owner then
outputChatBox('Dono do celular ' .. phoneID .. ': ' .. getPlayerName(owner), player)
else
outputChatBox('Dono do celular não está online ou celular não existe.', player)
end
end)
```
***
## bindPhonePlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:bindPhonePlayer(player)
```
**Required arguments**
* `player` (`player`): jogador que terá o keybind ativado.
**Comportamento**
* Ativa o keybind definido em `config.keyOpen` para o player.
* Útil quando `config.disableKeyOpen` é `true` e você quer ativar manualmente apenas para alguns players (ex.: players que possuem celular no inventário).
**Example**
```lua theme={null}
-- SERVER-SIDE (ativar keybind quando player pegar celular no inventário)
addEventHandler('onPlayerEquipItem', root, function(itemName)
if itemName == 'celular' then
exports['sqh_phone']:bindPhonePlayer(source)
end
end)
```
***
## unbindPhonePlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:unbindPhonePlayer(player)
```
**Required arguments**
* `player` (`player`): jogador que terá o keybind removido.
**Comportamento**
* Remove o keybind definido em `config.keyOpen` do player.
* Útil para remover o keybind quando o player dropar ou usar o celular no inventário.
**Example**
```lua theme={null}
-- SERVER-SIDE (remover keybind quando player dropar o celular)
addEventHandler('onPlayerDropItem', root, function(itemName)
if itemName == 'celular' then
exports['sqh_phone']:unbindPhonePlayer(source)
end
end)
```
***
## managerWifiController
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:managerWifiController(tableArguments)
```
**Required arguments**
* `tableArguments` (`table`): tabela com os argumentos da ação a ser executada. O campo `type` define a ação.
**Tipos disponíveis (`type`)**
### `'creationNetwork'` — Criar uma rede Wi-Fi
Campos obrigatórios:
* `type` = `'creationNetwork'`
* `name` (`string`): nome da rede.
* `position` (`table`): posição e tamanho da área de cobertura.
* `positionX`/`positionY` (`number`): coordenadas fixas (opcional, se não informado usa a posição do source).
* `width` (`number`): largura da área.
* `height` (`number`): altura da área.
Campos opcionais:
* `password` (`string`): senha da rede (padrão: sem senha).
* `public` (`boolean`): se a rede é pública.
* `networkType` (`string`): tipo da rede.
* `player` (`player`): player de referência (quando chamado sem `source`).
**Return**
* `true` em sucesso.
**Exemplo — criar rede**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('criawifi', function(player, _, name)
local px, py = getElementPosition(player)
exports['sqh_phone']:managerWifiController({
type = 'creationNetwork',
name = name or 'MeuWifi',
password = '1234',
public = false,
networkType = 'home',
player = player,
position = {
width = 30,
height = 30
}
})
outputChatBox('Rede criada!', player)
end)
```
***
## equipSpotifyJBL
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:equipSpotifyJBL(player)
```
**Required arguments**
* `player` (`player`): jogador que irá equipar a JBL.
**Comportamento**
* Equipa o model da JBL (definido em `config.jblModelObject`) no corpo do player.
* Ativa o sistema de bluetooth para o player.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('equiparJBL', function(player)
exports['sqh_phone']:equipSpotifyJBL(player)
end)
```
***
## unEquipSpotifyJBL
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:unEquipSpotifyJBL(player)
```
**Required arguments**
* `player` (`player`): jogador que irá desequipar a JBL.
**Comportamento**
* Remove o model da JBL do corpo do player sem dropar no chão.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('guardarJBL', function(player)
exports['sqh_phone']:unEquipSpotifyJBL(player)
end)
```
***
## dropSpotifyJBL
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:dropSpotifyJBL(player)
```
**Required arguments**
* `player` (`player`): jogador que irá dropar a JBL.
**Comportamento**
* Remove a JBL do corpo do player e a dropa no chão na posição do player.
* Cria um marker no chão para que outros players possam pegar a JBL.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('droparJBL', function(player)
exports['sqh_phone']:dropSpotifyJBL(player)
end)
```
***
## instagramVerifyAccount
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_phone']:instagramVerifyAccount(accountID, value)
```
**Required arguments**
* `accountID` (`number`): ID da conta do Instagram.
* `value` (`boolean`): `true` para verificar, `false` para remover a verificação.
**Comportamento**
* Define o status de verificação (selo azul) de uma conta do Instagram.
**Return**
* Retorno direto da função interna `instagram.verifyAccountAdmin`.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('verificarinsta', function(player, _, accountID)
exports['sqh_phone']:instagramVerifyAccount(tonumber(accountID), true)
outputChatBox('Conta verificada!', player)
end)
```
```lua theme={null}
-- SERVER-SIDE (remover verificação)
addCommandHandler('desverificarinsta', function(player, _, accountID)
exports['sqh_phone']:instagramVerifyAccount(tonumber(accountID), false)
outputChatBox('Verificação removida!', player)
end)
```
***
## Observações
* Todas as exports exigem que o resource já tenha sido liberado pela proteção do sistema.
* As funções acima seguem o que está exportado no `meta.xml` do `sqh_phone`.
* Para que `buyPhone` e `removePhonePlayer` funcionem corretamente, o player deve estar logado em uma conta (não guest).
* Os comandos `equiparJBL` e `droparJBL` já existem por padrão no script (quando `config.jblCommandsActive = true`). As exports são úteis para integração com outros sistemas.
# Configurações Phone System
Source: https://docs.squashcodes.com/pt/resources/phone-system/settings
Manual completo de configuração do Phone System. Saiba o que cada opção faz e como customizar o sistema para o seu servidor.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Precisa integrar o Phone System com outro script? Clique aqui
## Sobre as configurações
Todas as configurações do Phone System são feitas no arquivo `config/settings.lua`. O arquivo é organizado em seções, cada uma responsável por uma parte do sistema. Abaixo você encontra o manual completo de cada opção.
***
## 1. Licença
Configuração da licença de ativação do sistema.
| Opção | Descrição |
| --------------- | ---------------------------------------------------------------- |
| `license.Email` | E-mail da conta na Squash Company utilizado na compra do produto |
| `license.Key` | Chave de licença do produto |
```lua theme={null}
license = {
Email = 'seu@email.com',
Key = 'SUA_CHAVE_AQUI'
}
```
***
## 2. Integrações
Define quais sistemas externos o Phone System deve se integrar automaticamente.
| Opção | Descrição |
| --------------------------- | ------------------------------------------------------------------ |
| `integrations.sqh_groups` | Ativa integração com o sistema de grupos/gangues |
| `integrations.sqh_accounts` | Ativa integração com o sistema de contas/personagens |
| `integrations.sqh_custom` | Ativa integração com sistema de conta customizado (feito por você) |
| Valor | O que muda |
| ------- | -------------------------------------------------------- |
| `true` | A integração será ativada e os dados serão sincronizados |
| `false` | A integração não será usada |
```lua theme={null}
integrations = {
sqh_groups = true,
sqh_accounts = true,
sqh_custom = false
}
```
> Se `sqh_custom = true`, você deverá preencher as funções na seção `config.system` para buscar/salvar dados da conta manualmente.
***
## 3. Configurações Gerais
### 3.1 Database
| Opção | Descrição |
| ------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `config.isResetDatabase` | Se `true`, reseta todas as tabelas do banco de dados ao iniciar o resource. **CUIDADO: apaga todos os dados.** |
### 3.2 Tecla de abrir
| Opção | Descrição |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `config.keyOpen` | Tecla para abrir/fechar o celular. Padrão: `"K"` |
| `config.disableKeyOpen` | Se `true`, desabilita o keybind automático. Use junto com `bindPhonePlayer`/`unbindPhonePlayer` para controle manual |
### 3.3 Verificação antes de abrir
Callback chamado antes de abrir o celular. Retorne `false` para bloquear a abertura.
```lua theme={null}
config.verifyToOpen = function(player)
-- impede abrir o celular se o player estiver morto
if getElementHealth(player) == 0 then
return false
end
return true
end
```
### 3.4 Comportamento
| Opção | Tipo | Descrição |
| ----------------------------- | --------- | --------------------------------------------------------------------------------- |
| `config.showCursor` | `boolean` | Exibe o cursor ao abrir o celular |
| `config.haveOnlyOnePhone` | `boolean` | Se `true`, o player não pode ter mais de um celular |
| `config.acceptPhoneMessages` | `boolean` | Se `true`, ligações são convertidas em mensagens de WhatsApp (sem chamada de voz) |
| `config.blockLeftVehicle` | `boolean` | Se `true`, bloqueia o celular por alguns segundos após sair de um veículo |
| `config.blockLeftVehicleTime` | `number` | Tempo em ms de bloqueio após sair do veículo |
| `config.cursorBind` | `string` | Tecla para mostrar/esconder o cursor dentro do celular |
***
## 4. Compra de Celular (Markers)
Configura os markers de loja de celular no mapa.
| Opção | Tipo | Descrição |
| ------------------------------------------ | --------- | ------------------------------------- |
| `config.buyPhoneInfos.desactiveBuyMarkers` | `boolean` | Desativa os markers de compra no mapa |
| `config.buyPhoneInfos.valueToBuyPhone` | `number` | Preço do celular na loja |
### 4.1 Funções de dinheiro
Defina como o dinheiro é verificado e deduzido no seu servidor:
```lua theme={null}
config.buyPhoneInfos.verifyMoney = function(player)
-- retorne true se o player tem saldo suficiente
return getPlayerMoney(player) >= config.buyPhoneInfos.valueToBuyPhone
end
config.buyPhoneInfos.takeMoney = function(player, amount)
-- debite o valor do player
takePlayerMoney(player, amount)
end
```
### 4.2 Markers de loja
```lua theme={null}
config.buyPhoneInfos.markers = {
{x = 100.0, y = 200.0, z = 10.0}
}
```
### 4.3 Marker customizado
Callback chamado ao criar cada marker — permite personalizar cor/tipo:
```lua theme={null}
config.buyPhoneInfos.customMarkers = function(marker)
setMarkerColor(marker, 0, 150, 255, 200)
end
```
***
## 5. Model do Celular e JBL
### 5.1 Posição do Celular na Mão
Define onde o model do celular aparece no corpo do player enquanto o celular está aberto.
```lua theme={null}
config.phoneModelPosition = {x = 0.0, y = 0.0, z = 0.0, rx = 0.0, ry = 0.0, rz = 0.0}
config.phoneModelObject = 367 -- ID do objeto
```
### 5.2 JBL (Spotify)
| Opção | Tipo | Descrição |
| -------------------------- | --------- | ------------------------------------------------------------------------- |
| `config.jblModelObject` | `number` | ID do model da JBL |
| `config.jblModelPosition` | `table` | Posição/rotação no corpo do player |
| `config.jblDropRotation` | `table` | Rotação ao dropar no chão |
| `config.jblCommandsActive` | `boolean` | Se `true`, ativa os comandos `/equiparJBL` e `/droparJBL` automaticamente |
***
## 6. Sistema de Contas
### 6.1 Tipo de conta
| Opção | Valor | Descrição |
| --------------------------------------- | --------------- | ---------------------------------------------------- |
| `config.system.accountSave.accountType` | `"Account"` | Usa o sistema de contas nativo do MTA (loginAccount) |
| `config.system.accountSave.accountType` | `"ElementData"` | Usa ElementData para identificar o player |
Para `"ElementData"`, configure:
```lua theme={null}
config.system.accountSave.elementDataName = 'character:id' -- nome do ElementData
```
### 6.2 Formato do número de telefone
| Opção | Tipo | Descrição |
| ------------------------------ | -------- | --------------------------------------------------------------------------------------- |
| `config.system.numberType` | `string` | Padrão do número. Use `x` onde devem ser gerados dígitos aleatórios. Ex: `"9xxxx-xxxx"` |
| `config.system.numberQuantity` | `number` | Quantidade de dígitos `x` no padrão acima |
***
## 7. Eventos (Callbacks)
Callbacks chamados em ações do celular.
```lua theme={null}
config.events.onBuyPhone = function(player)
-- chamado quando o player compra/recebe um celular
outputChatBox('Você recebeu um celular!', player)
end
config.events.onOpenPhone = function(player)
-- chamado quando o celular é aberto
end
config.events.onClosePhone = function(player)
-- chamado quando o celular é fechado
end
```
***
## 8. Notificações (Infobox)
Funções para enviar notificações ao player. Personalize para usar o sistema de notificações do seu servidor.
```lua theme={null}
config.sendInfobox = function(player, text, type)
-- notificação server-side
-- type pode ser: 'success', 'error', 'info', 'warning'
outputChatBox('[Celular] ' .. text, player)
end
config.sendClientInfobox = function(player, text, type)
-- notificação client-side via triggerClientEvent
triggerClientEvent(player, 'minhaNotificacao', player, text, type)
end
```
***
## 9. Escala por Resolução
Define escala do celular para diferentes resoluções de tela.
```lua theme={null}
config.predefinedScaleValues = {
[1] = {width = 1920, height = 1080, scale = 1.0},
[2] = {width = 1280, height = 720, scale = 0.75},
-- adicione mais resoluções se necessário
}
```
***
## 10. Controles Bloqueados com Celular Aberto
Lista de controles do MTA que ficam desabilitados enquanto o celular estiver aberto.
```lua theme={null}
config.restrictionControls = {
{group = 0, control = 14}, -- enter vehicle
{group = 0, control = 16}, -- next weapon
-- ... adicione ou remova controles conforme necessário
}
```
Consulte a [lista de controles do MTA](https://wiki.multitheftauto.com/wiki/Control_names) para os IDs corretos.
***
## 11. Aplicativos
### 11.1 Aplicativos padrão (pré-instalados)
Lista de apps que estarão instalados no celular desde a criação, sem precisar baixar na loja:
```lua theme={null}
config.applicationsDefault = {
'whatsapp', 'phone', 'contacts', 'settings', 'camera', 'photos', 'calculator'
}
```
### 11.2 Aplicativos que não podem ser desinstalados
```lua theme={null}
config.applicationsBlockedDesinstall = {
'phone', 'settings', 'contacts'
}
```
### 11.3 Aplicativos disponíveis na loja
```lua theme={null}
config.applicationsReleased = {
'whatsapp', 'instagram', 'spotify', 'blaze', 'paypal', 'uber', 'maps', 'claro',
'google', 'youtube', 'cnn', 'clima', 'notes', 'camera', 'calculator', 'google_translate'
}
```
***
## 12. Configurações por Aplicativo
Todos os apps compartilham campos base de metadados usados pela AppStore:
| Campo | Tipo | Descrição |
| ------------------------- | -------- | ----------------------------------------------------------- |
| `name` | `string` | Nome exibido na AppStore |
| `icon` | `string` | Caminho do ícone |
| `description` | `string` | Descrição exibida na AppStore |
| `timeDownload` | `number` | Tempo em segundos para "baixar" o app na AppStore |
| `updatedAt` / `createdAt` | `number` | Timestamps Unix de criação/atualização exibidos na AppStore |
| `banners` | `table` | Lista de 3 imagens exibidas na página do app na AppStore |
***
### 12.1 AppStore (`config.apps.appstore`)
| Opção | Tipo | Descrição |
| ---------------------------- | -------- | --------------------------------------------------------- |
| `appsRecomendation` | `table` | Lista de nomes de apps exibidos como sugestões de busca |
| `applicationRecommended` | `string` | App em destaque na seção "App Recomendado" |
| `gameRecommended` | `string` | Jogo em destaque na seção "Jogo Recomendado" |
| `recentsPage.showNewApps` | `number` | Quantidade de novos apps exibidos na seção recentes |
| `recentsPage.showUpdateApps` | `number` | Quantidade de apps atualizados exibidos na seção recentes |
```lua theme={null}
["appstore"] = {
["appsRecomendation"] = {"whatsapp", "snake game", "youtube", "spotify", "instagram"},
["applicationRecommended"] = "spotify",
["gameRecommended"] = "snake",
["timeDownload"] = 15,
["recentsPage"] = {
["showNewApps"] = 6,
["showUpdateApps"] = 10,
}
}
```
***
### 12.2 WhatsApp (`config.apps.whatsapp`)
| Opção | Tipo | Descrição |
| ------------------ | ------------------ | ------------------------------------------------------- |
| `emojisQuantity` | `number` | Quantidade de emojis disponíveis no teclado |
| `stickersQuantity` | `number` | Quantidade de pacotes de stickers disponíveis |
| `returnName` | `function(player)` | Função que retorna o nome do player exibido no WhatsApp |
**Painel de configurações do app (`settingsPanel`)**
O WhatsApp possui um painel de configurações in-app com subpainéis:
| Subpainel | Opções disponíveis |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| `account` (Conta) | `verifyFaceID` — Exigir FaceID para entrar (toggle) |
| `privacity` (Privacidade) | `viewProfilePhoto` — Quem pode ver a foto (Todos / Contatos) · `confirmTicks` — Confirmação de visto (toggle) |
| `calls` (Ligações) | `silenceCallsStranger` — Receber ligações de estranhos (toggle) |
| `notifications` (Notificações) | `receiveNotifcations` — Receber notificações (toggle) · `soundNotifications` — Som de notificações (toggle) |
**Status Panel (`statusPanel`)**
| Opção | Tipo | Descrição |
| ------------------ | ------- | ------------------------------------------------------------------------- |
| `backgroundColors` | `table` | Lista de cores de fundo disponíveis para criar status (formato `tocolor`) |
| `fonts` | `table` | Lista de fontes disponíveis para texto nos status |
```lua theme={null}
["whatsapp"] = {
["emojisQuantity"] = 129,
["stickersQuantity"] = 1,
["returnName"] = function(player)
return getPlayerName(player)
end,
["statusPanel"] = {
["backgroundColors"] = {
[1] = tocolor(239, 179, 47, 255),
[2] = tocolor(145, 21, 21, 255),
[3] = tocolor(47, 135, 239, 255),
},
["fonts"] = {
[1] = "assets/fonts/apple_text_regular.ttf",
[2] = "assets/fonts/Roboto_Regular.ttf",
}
},
}
```
***
### 12.3 Spotify (`config.apps.spotify`)
| Opção | Tipo | Descrição |
| ------------------ | ------------------ | ------------------------------------------------------------------------------------ |
| `verifyPermission` | `function(player)` | Retorna `true` se o player pode usar o Spotify. Use para restringir por ACL ou cargo |
**`configurations` — Configurações de áudio**
| Opção | Tipo | Descrição |
| ----------------------------- | ------------------- | -------------------------------------------------------------- |
| `maxSoundVolume` | `number` | Volume máximo permitido (padrão: `10`) |
| `maxSoundDistance` | `number` | Distância máxima de audição em unidades do jogo (padrão: `10`) |
| `keyToGetJBL` | `string` | Tecla para pegar a JBL do chão (padrão: `"L"`) |
| `gendersMusic` | `table` | Gêneros musicais exibidos na interface (`gender`, `color`) |
| `colorsToCardsGender` | `table` | Cores dos cards de gênero (formato `tocolor`) |
| `getCarName` | `function(vehicle)` | Retorna o nome do veículo exibido no modo Bluetooth do carro |
| `verifyPermissionToBluetooth` | `function(player)` | Retorna `true` se o player pode usar o Bluetooth da JBL |
**`soundsVehicleConfigs` — Configuração por veículo**
| Opção | Tipo | Descrição |
| ------------------ | ------------------- | --------------------------------------------------------------------------------------------- |
| `getCarIdentifier` | `function(vehicle)` | Função que retorna o identificador do veículo (ex.: `getElementModel`) |
| `vehicles` | `table` | Tabela com configurações específicas por ID de veículo: `maxSoundVolume` e `maxSoundDistance` |
```lua theme={null}
["spotify"] = {
["configurations"] = {
['maxSoundVolume'] = 10,
['maxSoundDistance'] = 10,
['keyToGetJBL'] = "L",
['gendersMusic'] = {
{gender = "Funk", color = 1},
{gender = "Sertanejo", color = 2},
{gender = "Trap", color = 3},
},
['soundsVehicleConfigs'] = {
['getCarIdentifier'] = function(vehicle)
return getElementModel(vehicle)
end,
['vehicles'] = {
[402] = {maxSoundVolume = 10, maxSoundDistance = 10}
-- adicione mais modelos de veículo conforme necessário
}
},
['verifyPermissionToBluetooth'] = function(player)
return isObjectInACLGroup('user.'..getAccountName(getPlayerAccount(player)), aclGetGroup("Console"))
end,
['getCarName'] = function(vehicle)
return getVehicleNameFromModel(getElementModel(vehicle))
end,
},
['verifyPermission'] = function(player)
return true -- remova a restrição ou adicione verificação de ACL/cargo
end,
}
```
***
### 12.4 Uber (`config.apps.uber`)
| Opção | Tipo | Descrição |
| ---------------- | -------- | --------------------------------------------- |
| `pricePerKMCar` | `number` | Preço cobrado por KM em corridas de **carro** |
| `pricePerKMBike` | `number` | Preço cobrado por KM em corridas de **moto** |
**`settings` — Configurações de funcionamento**
| Opção | Tipo | Descrição |
| --------------- | ------------------------- | --------------------------------------------------------------------------------------- |
| `carsAllowed` | `table` | Tabela com IDs de modelos de veículos autorizados para Uber carro. Ex: `{[402] = true}` |
| `bikesAllowed` | `table` | Tabela com IDs de modelos de veículos autorizados para Uber moto |
| `getCarIdModel` | `function(vehicle)` | Retorna o ID do modelo do veículo |
| `getCarName` | `function(vehicle)` | Retorna o nome exibido do veículo durante a corrida |
| `getCarPlate` | `function(vehicle)` | Retorna a placa do veículo |
| `verifyMoney` | `function(player)` | Retorna o saldo atual do player (para verificar se pode pagar) |
| `takeMoney` | `function(player, value)` | Debita o valor da corrida do player |
| `giveMoney` | `function(player, value)` | Credita o valor da corrida ao motorista |
```lua theme={null}
["uber"] = {
["pricePerKMCar"] = 15.00,
["pricePerKMBike"] = 8.00,
['settings'] = {
['carsAllowed'] = {[402] = true}, -- ID 402 = Infernus
['bikesAllowed'] = {[522] = true}, -- ID 522 = NRG-500
getCarIdModel = function(vehicle)
return getElementModel(vehicle)
end,
getCarName = function(vehicle)
return getVehicleNameFromModel(getElementModel(vehicle))
end,
getCarPlate = function(vehicle)
return getVehiclePlateText(vehicle)
end,
verifyMoney = function(player)
return getPlayerMoney(player)
end,
takeMoney = function(player, value)
return takePlayerMoney(player, value)
end,
giveMoney = function(player, value)
return givePlayerMoney(player, value)
end
}
}
```
***
### 12.5 Maps (`config.apps.maps`)
| Opção | Tipo | Descrição |
| ------------------ | ------- | -------------------------------------------------------- |
| `localsConfig` | `table` | Lista de locais fixos exibidos no mapa do app |
| `suggestionsLocal` | `table` | Índices da `localsConfig` exibidos como sugestões no app |
**Campos de cada item em `localsConfig`:**
| Campo | Tipo | Descrição |
| -------------- | -------- | ----------------------------------------------- |
| `nameLocation` | `string` | Nome exibido do local |
| `mapPosition` | `table` | Posição `{x, y}` no mapa 2D do app |
| `position` | `table` | Tamanho do ícone: `{width, height}` |
| `typeIcon` | `string` | Tipo do ícone. Use `"fixed"` para ícones padrão |
| `id` | `number` | ID do blip do MTA usado como ícone |
```lua theme={null}
["maps"] = {
["localsConfig"] = {
[1] = {nameLocation = "Delegacia", mapPosition = {x = 1392, y = 247}, position = {width = 22, height = 22}, typeIcon = "fixed", id = 38},
[2] = {nameLocation = "Porto", mapPosition = {x = 2308, y = -849}, position = {width = 22, height = 22}, typeIcon = "fixed", id = 37},
},
["suggestionsLocal"] = {1, 2}, -- índices da tabela localsConfig
}
```
***
### 12.6 Claro (`config.apps.claro`)
| Opção | Tipo | Descrição |
| ------------- | -------------------------- | -------------------------------------------------------- |
| `plans` | `table` | Lista de planos de dados disponíveis para compra |
| `moneyVerify` | `function(player)` | Retorna o saldo do player para verificar se pode comprar |
| `moneyTake` | `function(player, amount)` | Debita o valor do plano do player |
**Campos de cada plano em `plans`:**
| Campo | Tipo | Descrição |
| ---------------- | -------- | ------------------------------------------------------- |
| `gigabyteAmount` | `string` | Quantidade de GB do plano (ex: `"10"`) — máximo: `"99"` |
| `displayPrice` | `string` | Preço exibido na interface (ex: `"R$ 12.000"`) |
| `price` | `number` | Valor real debitado do player |
```lua theme={null}
["claro"] = {
["configurations"] = {
["plans"] = {
{gigabyteAmount = "01", displayPrice = "R$ 1.500", price = 1500},
{gigabyteAmount = "05", displayPrice = "R$ 6.500", price = 6500},
{gigabyteAmount = "10", displayPrice = "R$ 12.000", price = 12000},
{gigabyteAmount = "20", displayPrice = "R$ 22.000", price = 22000},
-- máximo permitido: 99 GB e preço até 99.999
},
['moneyVerify'] = function(player)
return getPlayerMoney(player)
end,
['moneyTake'] = function(player, amount)
return takePlayerMoney(player, amount)
end,
}
}
```
***
### 12.7 Blaze (`config.apps.blaze`)
**`configurations` — Configurações gerais da roleta**
| Opção | Tipo | Descrição |
| ---------------------------- | -------- | ------------------------------------------------------------------ |
| `timeToStartRound` | `number` | Tempo em ms para iniciar a rodada após o jogador clicar em iniciar |
| `timeDuringRoullete` | `number` | Tempo em ms que a roleta fica girando até revelar o resultado |
| `depositValues` | `table` | Valores pré-definidos de depósito rápido |
| `withdrawValues` | `table` | Valores pré-definidos de saque rápido |
| `percentageAffiliationBonus` | `number` | % de bonus recebido pelo afiliador quando alguém usa seu código |
| `percentageBonusAffiliate` | `number` | % de bonus recebido pelo afiliado no próximo depósito |
**`moneyOptions` — Integração de dinheiro**
| Opção | Tipo | Descrição |
| ----------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `walletMoney` | `string` | Fonte do dinheiro da carteira: `"Game"`, `"ElementData"`, `"Function"` ou `"Disabled"` |
| `walletMoneyData` | `string` | Nome do ElementData (usado quando `walletMoney = "ElementData"`) |
| `walletFunction` | `function(player, moneyValue, typeManage)` | Função customizada de controle da carteira. `typeManage` = `"withdraw"` ou `"deposit"`. Retorne `true` em sucesso |
| `bankMoney` | `string` | Fonte do dinheiro bancário: `"ElementData"`, `"Function"` ou `"Disabled"` |
| `bankMoneyData` | `string` | Nome do ElementData do banco |
| `bankFunction` | `function(player, moneyValue, typeManage)` | Função customizada de controle do banco |
**`logsDiscord` — Logs no Discord**
| Opção | Tipo | Descrição |
| ----------------- | --------- | -------------------------------------------------------------------- |
| `active` | `boolean` | Se `true`, envia notificações no Discord para cada evento financeiro |
| `roundWebhook` | `string` | URL do webhook para logs de rodadas |
| `depositWebhook` | `string` | URL do webhook para logs de depósitos |
| `withdrawWebhook` | `string` | URL do webhook para logs de saques |
| `rewardWebhook` | `string` | URL do webhook para logs de recompensas |
**`rewardsConfigurations` — Sistema de recompensas por nível**
| Opção | Tipo | Descrição |
| -------------- | -------- | ------------------------------------------------------------------------------------------------- |
| `typeReward` | `string` | Quando recompensar: `"Rounds"` (por rodadas jogadas), `"Wins"` (por vitórias) ou `"Both"` (ambos) |
| `rewardsLevel` | `table` | Define qual recompensa é dada ao atingir cada nível (índice = nível) |
**Tipos de recompensa disponíveis:**
| Tipo | Descrição |
| ------------------ | --------------------------------------- |
| `"money"` | Saldo em dinheiro direto na Blaze |
| `"cashbackRounds"` | Cashback de X% por X rodadas de apostas |
| `"cashbackTime"` | Cashback de X% durante X segundos |
| `"roundsFree"` | X rodadas grátis de X valor |
| `"depositBonus"` | Bônus de X% no próximo depósito |
**Campos dos valores em `rewardsLevel`:**
| Campo | Descrição |
| ------------------- | -------------------------------------------------------------------------------------------------------- |
| `rewards` | Lista de tipos de recompensa possíveis. Se tiver mais de um, o sistema sorteia aleatoriamente entre eles |
| `values.percentage` | Intervalo `{min, max}` da porcentagem |
| `values.rounds` | Intervalo de quantidade de rodadas |
| `values.value` | Intervalo do valor em dinheiro |
| `values.time` | Intervalo de tempo em segundos |
| `values.timeExpire` | Intervalo de validade da recompensa em segundos |
```lua theme={null}
["blaze"] = {
["configurations"] = {
["timeToStartRound"] = 15000,
["timeDuringRoullete"] = 6000,
["depositValues"] = {100, 1000, 10000},
["withdrawValues"] = {50, 500, 5000},
["percentageAffiliationBonus"] = 10,
["percentageBonusAffiliate"] = 30,
["moneyOptions"] = {
["walletMoney"] = "Game", -- usa getPlayerMoney/takePlayerMoney
["walletFunction"] = function(player, moneyValue, typeManage)
if typeManage == "deposit" then
return getPlayerMoney(player) >= moneyValue
end
return false
end,
["bankMoney"] = "Disabled",
['logsDiscord'] = {
['active'] = true,
['roundWebhook'] = "https://discord.com/api/webhooks/...",
['depositWebhook'] = "https://discord.com/api/webhooks/...",
['withdrawWebhook'] = "https://discord.com/api/webhooks/...",
['rewardWebhook'] = "https://discord.com/api/webhooks/...",
}
},
["rewardsConfigurations"] = {
["typeReward"] = "Both",
["rewardsLevel"] = {
[2] = {rewards = {"cashbackRounds"}, values = {percentage = {50, 20}, rounds = {1, 3}, value = {0}, time = {0}, timeExpire = {80, 100}}},
[5] = {rewards = {"money"}, values = {percentage = {0}, rounds = {0}, value = {3000, 9000}, time = {0}, timeExpire = {300, 350}}},
[6] = {rewards = {"cashbackTime"}, values = {percentage = {10, 35}, rounds = {0}, value = {0}, time = {100, 120}, timeExpire = {300, 350}}},
[7] = {rewards = {"roundsFree"}, values = {percentage = {0}, rounds = {3}, value = {2, 3}, time = {0}, timeExpire = {300, 350}}},
[8] = {rewards = {"depositBonus"}, values = {percentage = {10, 30, 45}, rounds = {0}, value = {0}, time = {0}, timeExpire = {300, 350}}},
},
},
},
}
```
***
### 12.8 Paypal (`config.apps.paypal`)
**`configurations` — Configurações gerais**
| Opção | Tipo | Descrição |
| ------------------------- | ------------------ | ------------------------------------------------------------------------------- |
| `blockDepositInPhone` | `boolean` | Se `true`, o jogador não pode fazer depósito pelo celular |
| `getIDPlayer` | `function(player)` | Retorna o ID do jogador usado como identificador da conta PayPal |
| `typesTransaction` | `table` | Nomes dos tipos de transação exibidos no histórico |
| `existsTaxOpenAccount` | `boolean` | Se `true`, gera um boleto de taxa para abrir a conta PayPal |
| `valueTaxOpenAccount` | `number` | Valor da taxa de abertura de conta (usado quando `existsTaxOpenAccount = true`) |
| `minInvestmentPercentage` | `number` | % mínima de retorno em investimentos |
| `maxInvestmentPercentage` | `number` | % máxima de retorno em investimentos |
| `fineDueDatePercentage` | `number` | % de multa por dia aplicada em boletos vencidos |
**`walletMoney` — Integração com dinheiro**
| Opção | Tipo | Descrição |
| ----------- | ------------------------- | -------------------------------------- |
| `typeGet` | `function(player)` | Retorna o saldo da carteira do jogador |
| `takeMoney` | `function(player, money)` | Debita da carteira |
| `giveMoney` | `function(player, money)` | Credita na carteira |
**`transferInfos.logsDiscord` — Logs no Discord**
| Campo | Descrição |
| --------------------- | ----------------------------------------------- |
| `active` | Se `true`, envia logs de todas as movimentações |
| `transferWebhook` | URL do webhook para transferências |
| `depositWebhook` | URL do webhook para depósitos |
| `withdrawWebhook` | URL do webhook para saques |
| `investimentsWebhook` | URL do webhook para investimentos |
```lua theme={null}
["paypal"] = {
["configurations"] = {
["blockDepositInPhone"] = false,
["getIDPlayer"] = function(player)
return getElementData(player, 'ID')
end,
["typesTransaction"] = {
[1] = "Transferência Via Pix",
[2] = "Depósito",
[3] = "Saque",
[4] = "Investimento",
},
['existsTaxOpenAccount'] = true,
['valueTaxOpenAccount'] = 100,
["minInvestmentPercentage"] = 3,
["maxInvestmentPercentage"] = 20,
["fineDueDatePercentage"] = 10,
["walletMoney"] = {
typeGet = function(player)
return getPlayerMoney(player)
end,
takeMoney = function(player, money)
return takePlayerMoney(player, money)
end,
giveMoney = function(player, money)
return givePlayerMoney(player, money)
end
},
['transferInfos'] = {
['logsDiscord'] = {
['active'] = true,
['transferWebhook'] = "https://discord.com/api/webhooks/...",
['depositWebhook'] = "https://discord.com/api/webhooks/...",
['withdrawWebhook'] = "https://discord.com/api/webhooks/...",
['investimentsWebhook'] = "https://discord.com/api/webhooks/...",
}
}
},
}
```
***
### 12.9 Staff (`config.apps.staff`)
| Opção | Tipo | Descrição |
| ------------------ | ------------------ | --------------------------------------------------- |
| `verifyPermission` | `function(player)` | Retorna `true` se o player tem acesso ao app Staff |
| `apps` | `table` | Lista de apps (por nome) que o staff pode gerenciar |
| `subPanelsApps` | `table` | Define subpainéis por app dentro do Staff |
**`subPanelsApps` — Subpainéis disponíveis**
| App | Subpainel | Descrição |
| ----------- | -------------------------------- | -------------------------------------------------------- |
| `whatsapp` | `loadChannels = true` | Carrega os canais do WhatsApp para gerenciamento |
| `instagram` | `loadVerifyAccountsInsta = true` | Carrega contas do Instagram para verificação (selo azul) |
| `Geral` | `action = 'changeNumber'` | Botão para trocar o número de telefone de um jogador |
| `Geral` | `action = 'createWifi'` | Botão para criar uma rede Wi-Fi |
```lua theme={null}
["staff"] = {
['verifyPermission'] = function(player)
return isObjectInACLGroup('user.'..getAccountName(getPlayerAccount(player)), aclGetGroup("Admin"))
end,
["apps"] = {"whatsapp", "instagram"},
["subPanelsApps"] = {
["whatsapp"] = {
{subtitle = "Canais", loadChannels = true}
},
["instagram"] = {
{subtitle = "Contas verificadas", loadVerifyAccountsInsta = true}
},
["Geral"] = {
{subtitle = "Trocar número de telefone", button = true, action = 'changeNumber'},
{subtitle = "Criar Wi-Fi", button = true, action = 'createWifi'}
}
},
}
```
***
### 12.10 Google Tradutor (`config.apps.google_translate`)
| Opção | Tipo | Descrição |
| -------------- | -------- | -------------------------------------------------------------------------------- |
| `languageTo` | `string` | Idioma de **origem** padrão (ex: `'pt'`, `'en'`, `'es'`, `'de'`, `'ja'`, `'fr'`) |
| `languageFrom` | `string` | Idioma de **destino** padrão |
```lua theme={null}
["google_translate"] = {
['languageTo'] = 'pt', -- escrevendo em português
['languageFrom'] = 'en', -- traduzindo para inglês
}
```
***
### 12.11 Configurações (`config.apps.settings`)
| Opção | Tipo | Descrição |
| ------------------ | -------- | ----------------------------------------- |
| `timeToResetPhone` | `number` | Tempo em segundos para formatar o celular |
**`profileInfos` — Informações do perfil**
| Opção | Tipo | Descrição |
| ----------------- | ------------------ | ------------------------------------------------ |
| `getProfileName` | `function(player)` | Retorna o nome exibido no perfil do app Settings |
| `getProfileID` | `function(player)` | Retorna o ID exibido no perfil |
| `getProfilePhoto` | `function(player)` | Retorna o caminho da foto de perfil |
**`notificacoes` — Configurações de notificações in-app**
Lista de grupos de notificações que o jogador pode ativar/desativar. Cada grupo tem `collumName` (título da coluna ou `false`) e itens com `name` e `data` (chave salva nas preferências).
**`wallpaperDefaults` — Wallpapers disponíveis**
Lista de wallpapers padrão. Cada item tem `{wallpaper = N}` onde `N` é o número do arquivo de wallpaper em `assets/images/wallpapers/`.
```lua theme={null}
["settings"] = {
['timeToResetPhone'] = 5,
["profileInfos"] = {
["getProfileName"] = function(player)
return getAccountName(getPlayerAccount(player))
end,
["getProfileID"] = function(player)
return getElementData(player, "id") or "#0000"
end,
["getProfilePhoto"] = function(player)
return "assets/images/apps/settings/avatar.png"
end
},
}
```
***
## 13. Setup (Aparência Inicial)
Configura as opções de personalização que aparecem durante o setup inicial do celular.
### 13.1 Capas disponíveis
Cada capa tem dois campos de cor: `colorShowcase` (cor de destaque exibida na tela de seleção) e `colorBackground` (cor de fundo da capa aplicada ao celular). Ambos usam o formato `tocolor(R, G, B, A)`.
O sistema vem com as seguintes 10 capas padrão:
| # | Nome | Preview (R, G, B) |
| -- | --------------- | ----------------- |
| 1 | Preto | `(27, 27, 27)` |
| 2 | Prata | `(205, 205, 205)` |
| 3 | Azul-glacial | `(155, 225, 223)` |
| 4 | Roxo-escuro | `(82, 78, 102)` |
| 5 | Caramelo | `(161, 122, 91)` |
| 6 | Verde | `(66, 157, 97)` |
| 7 | Azul-aço | `(85, 131, 160)` |
| 8 | Vermelho-escuro | `(136, 56, 54)` |
| 9 | Rosa | `(170, 96, 146)` |
| 10 | Verde-claro | `(204, 224, 175)` |
```lua theme={null}
config.setup.appearance.cases = {
{colorShowcase = tocolor(27, 27, 27, 255), colorBackground = tocolor(27, 27, 27, 255)},
{colorShowcase = tocolor(205, 205, 205, 255), colorBackground = tocolor(205, 205, 205, 255)},
{colorShowcase = tocolor(155, 225, 223, 255), colorBackground = tocolor(155, 225, 223, 255)},
{colorShowcase = tocolor(82, 78, 102, 255), colorBackground = tocolor(82, 78, 102, 255)},
{colorShowcase = tocolor(161, 122, 91, 255), colorBackground = tocolor(161, 122, 91, 255)},
{colorShowcase = tocolor(66, 157, 97, 255), colorBackground = tocolor(66, 157, 97, 255)},
{colorShowcase = tocolor(85, 131, 160, 255), colorBackground = tocolor(85, 131, 160, 255)},
{colorShowcase = tocolor(136, 56, 54, 255), colorBackground = tocolor(136, 56, 54, 255)},
{colorShowcase = tocolor(170, 96, 146, 255), colorBackground = tocolor(170, 96, 146, 255)},
{colorShowcase = tocolor(204, 224, 175, 255), colorBackground = tocolor(204, 224, 175, 255)},
}
```
Para **adicionar** uma nova capa, acrescente uma nova entrada com os valores RGBA desejados.
***
## 14. Tela de Bloqueio (Lockscreen)
### 14.1 Sistema de Hacking
| Opção | Tipo | Descrição |
| --------------------------------------------- | -------- | --------------------------------------------------------- |
| `config.lockscreen.hacking.percentageDefault` | `number` | Porcentagem padrão de chance de hackear o celular (0-100) |
***
## 15. Widgets
Configura o painel de widgets deslizante. O painel é organizado em **linhas** (`rows`), e cada linha pode ter múltiplos widgets lado a lado.
### Estrutura de uma linha:
| Campo | Tipo | Descrição |
| --------------- | -------- | ------------------------------------------------- |
| `spacingHeight` | `number` | Espaçamento vertical entre esta linha e a próxima |
| `[N]` | `table` | Cada índice numérico é um widget nesta linha |
### Campos de cada widget:
| Campo | Tipo | Descrição |
| ------------- | --------------------- | --------------------------------------------------------- |
| `nameWidget` | `string` | Nome do widget (deve corresponder a um widget registrado) |
| `description` | `string` | Texto descritivo exibido abaixo do nome |
| `width` | `number` | Largura em unidades de grade (1 a 4) |
| `height` | `number` | Altura em unidades de grade |
| `spacingItem` | `number` *(opcional)* | Espaçamento lateral deste item |
```lua theme={null}
config.widgetsPanel = {
-- Linha 1: widget do Spotify (2x2) + outro widget (2x2)
{
spacingHeight = 0,
[1] = {nameWidget = "Spotify", description = "Que tal músicas?", width = 2, height = 2, spacingItem = 23},
[2] = {nameWidget = "Clock", description = "Horário atual", width = 2, height = 2},
},
-- Linha 2: widget grande (4x1)
{
spacingHeight = 10,
[1] = {nameWidget = "Battery", description = "Nível da bateria", width = 4, height = 1},
},
}
```
O `width` define quantas colunas do grid o widget ocupa. Com `width = 4`, o widget ocupa a linha inteira. Com `width = 2`, dois widgets cabem lado a lado.
***
## 16. Cores
Define a paleta de cores global do sistema.
| Chave | Descrição |
| --------------------- | -------------------------- |
| `config.colors.black` | Cor preta principal |
| `config.colors.white` | Cor branca principal |
| `config.colors.green` | Cor de sucesso/confirmação |
| `config.colors.red` | Cor de erro/alerta |
As cores são usadas internamente na interface e podem ser sobrescritas para personalização visual.
***
## 17. Tradução e Idioma
### 17.1 Idioma padrão
| Opção | Tipo | Descrição |
| -------------------- | -------- | ----------------------------------------- |
| `translate.language` | `string` | Idioma padrão. Ex: `"PT"`, `"EN"`, `"ES"` |
| `translate.currency` | `string` | Símbolo da moeda. Ex: `"R$"`, `"$"` |
### 17.2 Textos do sistema
Os textos da interface são armazenados em `translate.texts`. Você pode alterar qualquer texto para o idioma do seu servidor.
```lua theme={null}
translate.texts = {
not_have_phone = 'Você não possui um celular.',
openButtonPrompt = 'Pressione [K] para abrir o celular',
-- ... demais textos
}
```
### 17.3 Saudações por horário
```lua theme={null}
translate.greetings = {
{from = 6, to = 12, text = 'Bom dia'},
{from = 12, to = 18, text = 'Boa tarde'},
{from = 18, to = 24, text = 'Boa noite'},
{from = 0, to = 6, text = 'Boa madrugada'},
}
```
***
## Dicas Finais
* Após qualquer alteração no `config/settings.lua`, você deve reiniciar o resource com `restart sqh_phone`.
* **Nunca** ative `config.isResetDatabase = true` em produção com dados reais — isso apagará todo o banco de dados do sistema.
* Para integrar com sistemas de inventário externos, use a combinação de `config.disableKeyOpen = true` + `bindPhonePlayer` e `unbindPhonePlayer` via exports.
* Se o celular não abrir após configurar `verifyToOpen`, certifique-se que a função retorna `true` para os players corretos.
# Exports Radar System
Source: https://docs.squashcodes.com/pt/resources/radar-system/exports
Adquiriu o Radar System e está com dúvidas do sistema? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Radar system é unir performance, personalização e controle total.
O jogador tem liberdade para configurar o mapa do jeito que quiser, e o dono do servidor tem poder absoluto para definir o padrão, limitar opções e integrar com outros sistemas.
Com as funções exportadas, você pode:
* Controlar a visualização da minimap e bigmap;
* Criar rotas personalizadas no GPS (útil para sistemas com rotas de entrega, empregos, missões, etc.);
* Criar zonas dinâmicas no radar/bigmap, com opções de renderização, ícones personalizados e cores (ótimo para demarcar safe zones, territórios, zonas de perigo, etc.);
* E muito mais, com a flexibilidade de integrar essas funcionalidades em outros sistemas.
## Funções Exportadas
### Client-side
* [changeMinimapVisualization](#changeminimapvisualization) -> `Liga ou desliga a minimap`
* [changeBigmapVisualization](#changebigmapvisualization) -> `Abre ou fecha o bigmap`
* [createGPSRoute](#creategpsroute) -> `Cria/atualiza destino do GPS para o jogador`
### Server-side
* [changeMinimapVisualization](#changeminimapvisualization) -> `Liga ou desliga a minimap para um player`
* [changeBigmapVisualization](#changebigmapvisualization) -> `Abre ou fecha o bigmap para um player`
* [createRadarZone](#createradarzone) -> `Cria uma zona dinâmica no radar/bigmap`
* [removeRadarZone](#removeradarzone) -> `Remove uma zona dinâmica`
* [getRadarZones](#getradarzones) -> `Retorna todas as zonas dinâmicas`
## changeMinimapVisualization
**Side:** `client` e `server`
**Client syntax**
```lua theme={null}
exports['sqh_radar']:changeMinimapVisualization('on' or 'off')
```
**Server syntax**
```lua theme={null}
exports['sqh_radar']:changeMinimapVisualization(player, 'on' or 'off')
```
**Required arguments**
* `state` (`string`): `'on'` para ligar ou `'off'` para desligar.
**Server required arguments**
* `player` (`player`): jogador alvo que terá a minimap ligada/desligada.
* `state` (`string`): `'on'` para ligar ou `'off'` para desligar.
**Return (server)**
* `true` em sucesso.
* `false` em falha (player inválido, estado inválido, ou cliente ainda não liberado).
**Example**
```lua theme={null}
-- CLIENT-SIDE
bindKey('F7', 'down', function()
exports['sqh_radar']:changeMinimapVisualization('off')
end)
```
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('minimapoff', function(player)
local ok = exports['sqh_radar']:changeMinimapVisualization(player, 'off')
outputChatBox(ok and 'Minimap desligada' or 'Falha ao desligar minimap', player)
end)
```
## changeBigmapVisualization
**Side:** `client` e `server`
**Client syntax**
```lua theme={null}
exports['sqh_radar']:changeBigmapVisualization('on' or 'off')
```
**Server syntax**
```lua theme={null}
exports['sqh_radar']:changeBigmapVisualization(player, 'on' or 'off')
```
**Required arguments**
* `state` (`string`): `'on'` para abrir ou `'off'` para fechar.
**Server required arguments**
* `player` (`player`): jogador alvo que terá o bigmap alterado.
* `state` (`string`): `'on'` para abrir ou `'off'` para fechar.
**Comportamento**
* Em `'on'`, abre o bigmap com fluxo completo (cursor, navegação e render).
* Em `'off'`, fecha o bigmap caso esteja aberto.
**Return (server)**
* `true` em sucesso.
* `false` em falha (player inválido, estado inválido, ou cliente ainda não liberado).
**Example**
```lua theme={null}
-- CLIENT-SIDE
addCommandHandler('bigmapoff', function()
exports['sqh_radar']:changeBigmapVisualization('off')
end)
```
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('bloquearmapa', function(player)
local ok = exports['sqh_radar']:changeBigmapVisualization(player, 'off')
outputChatBox(ok and 'Bigmap fechado' or 'Falha ao fechar bigmap', player)
end)
```
## createGPSRoute
**Side:** `client` e `server`
**Client syntax**
```lua theme={null}
exports['sqh_radar']:createGPSRoute(player, x, y, z)
```
**Server syntax**
```lua theme={null}
exports['sqh_radar']:createGPSRoute(player, x, y, z)
```
**Required arguments**
* `player` (`player`)
* No client: deve ser o `localPlayer`.
* No server: player alvo que receberá a rota.
* `x` (`number`): coordenada X do destino.
* `y` (`number`): coordenada Y do destino.
**Optional arguments**
* `z` (`number`): coordenada Z do destino (padrão `0`).
**Return**
* `true` quando a rota é criada/atualizada.
* `false` em falha (principalmente no server: player inválido ou coordenadas inválidas).
**Client example**
```lua theme={null}
-- CLIENT-SIDE
addCommandHandler('rotacasa', function()
local created = exports['sqh_radar']:createGPSRoute(localPlayer, 1480.25, -1732.80, 13.55)
outputChatBox(created and 'Rota criada/atualizada' or 'Falha ao criar rota')
end)
```
**Server example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('setrota', function(player)
local success = exports['sqh_radar']:createGPSRoute(player, 1480.25, -1732.80, 13.55)
outputChatBox(success and 'Rota enviada para você' or 'Falha ao enviar rota', player)
end)
```
## createRadarZone
**Side:** `server`
**Syntax**
```lua theme={null}
local zoneIdOrFalse = exports['sqh_radar']:createRadarZone(zoneData)
```
**Required arguments**
* `zoneData` (`table`) com campos obrigatórios:
* `id` (`string`)
* `x` (`number`)
* `y` (`number`)
* `width` (`number > 0`)
* `height` (`number > 0`)
**Optional fields**
* `name` (`string`) - padrão: `id`
* `owner` (`string`)
* `renderMode` (`'name'` ou `'blip'`)
* `blipId` (`number`)
* `blip` (`number`) (alias de `blipId`)
* `color` (`'#RRGGBB'`)
* `icon` (`string`) caminho de ícone
**Return**
* `string` com o ID normalizado da zona em sucesso.
* `false` em falha.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('criarzona', function(player)
local px, py = getElementPosition(player)
local zoneId = exports['sqh_radar']:createRadarZone({
id = 'zona_evento',
name = 'Zona de Evento',
owner = 'Administração',
x = px - 25,
y = py - 25,
width = 50,
height = 50,
renderMode = 'blip',
blipId = 41,
color = '#E13B3B'
})
outputChatBox(zoneId and ('Zona criada: ' .. zoneId) or 'Falha ao criar zona', player)
end)
```
## removeRadarZone
**Side:** `server`
**Syntax**
```lua theme={null}
local success = exports['sqh_radar']:removeRadarZone(zoneId)
```
**Required arguments**
* `zoneId` (`string`): ID da zona a remover.
**Return**
* `true` se removeu.
* `false` se não encontrou ou falhou.
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('removerzona', function(player, _, zoneId)
if not zoneId then
outputChatBox('Use: /removerzona ', player)
return
end
local success = exports['sqh_radar']:removeRadarZone(zoneId)
outputChatBox(success and 'Zona removida' or 'Zona não encontrada', player)
end)
```
## getRadarZones
**Side:** `server`
**Syntax**
```lua theme={null}
local zones = exports['sqh_radar']:getRadarZones()
```
**Return**
* `table` de zonas dinâmicas no formato:
```lua theme={null}
{
{
id = 'zona_id',
name = 'Nome',
owner = 'Owner',
icon = 'assets/blips/41.png',
renderMode = 'name' or 'blip',
blipId = 41,
color = '#81B3FF',
x = 1000,
y = -1200,
width = 40,
height = 40
},
...
}
```
**Example**
```lua theme={null}
-- SERVER-SIDE
addCommandHandler('listarzonas', function(player)
local zones = exports['sqh_radar']:getRadarZones() or {}
outputChatBox('Total de zonas: ' .. tostring(#zones), player)
for _, zone in ipairs(zones) do
outputChatBox(string.format('- %s (%s)', tostring(zone.name), tostring(zone.id)), player)
end
end)
```
## Observações
* Todas as exports exigem que o resource já tenha sido liberado pela proteção.
* As funções acima seguem o que está exportado no `meta.xml` do `sqh_radar`.
# Configurações Radar System
Source: https://docs.squashcodes.com/pt/resources/radar-system/settings
Guia completo do config/settings.lua do Radar System.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
A proposta do Radar system é unir performance, personalização e controle total.
O jogador tem liberdade para configurar o mapa do jeito que quiser, e o dono do servidor tem poder absoluto para definir o padrão, limitar opções e integrar com outros sistemas.
Com as funções exportadas, você pode:
* Controlar a visualização da minimap e bigmap;
* Criar rotas personalizadas no GPS (útil para sistemas com rotas de entrega, empregos, missões, etc.);
* Criar zonas dinâmicas no radar/bigmap, com opções de renderização, ícones personalizados e cores (ótimo para demarcar safe zones, territórios, zonas de perigo, etc.);
* E muito mais, com a flexibilidade de integrar essas funcionalidades em outros sistemas.
## Visão Geral
Este guia cobre **todo o arquivo** `config/settings.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você saber quando usar `true` ou `false`.
* Você configurar o radar sem precisar entrar em detalhes técnicos.
## Antes de Começar
* Arquivo de configuração: `config/settings.lua`
* Depois de alterar a config: reinicie o resource (`restart sqh_radar`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## 1) `Config.Map`
Controla tamanho e imagens do mapa.
| Opção | O que muda |
| ------------------------------------ | ----------------------------------------- |
| `textureSize` | Define o tamanho base da textura do mapa. |
| `textureSizeByTheme.default.w/h` | Tamanho do mapa no tema padrão. |
| `textureSizeByTheme.default.preview` | Imagem de preview do tema padrão. |
| `textureSizeByTheme.light.w/h` | Tamanho do mapa no tema claro. |
| `textureSizeByTheme.light.preview` | Imagem de preview do tema claro. |
| `textureSizeByTheme.dark.w/h` | Tamanho do mapa no tema escuro. |
| `textureSizeByTheme.dark.preview` | Imagem de preview do tema escuro. |
| `worldSize` | Tamanho do mundo usado pelo radar. |
***
## 2) `Config.Callbacks`
Ações executadas quando o mapa abre/fecha e quando a rota termina.
| Callback | Quando acontece | Exemplo de uso |
| ----------------- | -------------------------- | -------------------- |
| `onMapOpen` | Quando o mapa grande abre | Esconder chat/HUD |
| `onMapClose` | Quando o mapa grande fecha | Reexibir chat/HUD |
| `onRouteComplete` | Quando rota é concluída | Tocar som, aviso etc |
Exemplo simples:
```lua theme={null}
onMapOpen = function()
showChat(false)
end,
onMapClose = function()
showChat(true)
end
```
***
## 3) `Config.FullMap`
Configura o mapa grande (bigmap).
### `keybinds`
| Opção | O que muda |
| -------- | -------------------------------------- |
| `toggle` | Tecla para abrir/fechar o mapa grande. |
| `mark` | Tecla para marcar destino no mapa. |
### `ui`
| Opção | O que muda |
| ------------- | ------------------------------------------ |
| `accentColor` | Cor principal da interface do mapa grande. |
### `hints`
Lista de dicas exibidas no rodapé do mapa.
Campos por item:
* `type`: tipo da dica (`mouse_left`, `mouse_right`, `mouse_middle`, `arrows`, `keycap`)
* `icon`: ícone (quando aplicável)
* `key`: tecla exibida no keycap (quando `type = 'keycap'`)
* `action`: texto da ação
### `categories`
Define categorias e filtros de blips no mapa.
Campos da categoria:
* `title`: nome da categoria
Campos de cada item:
* `title`: nome do filtro
* `icon`: ID do ícone
* `blip_ids`: IDs de blip que esse filtro controla
* `state`: estado inicial
* `true`: começa ligado
* `false`: começa desligado
***
## 4) `Config.Radar`
Configura o minimapa (radar pequeno).
### `appearance`
| Opção | O que muda |
| -------------- | ------------------------------------- |
| `cornerRadius` | Arredondamento do minimapa |
| `zoomFactor` | Nível de zoom |
| `margin` | Distância das bordas da tela |
| `waterColor` | Cor da água no minimapa (`{R, G, B}`) |
| `outline` | Cor da borda do minimapa |
### `route`
| Opção | O que muda |
| ----------- | -------------------------- |
| `lineWidth` | Espessura da linha da rota |
| `lineColor` | Cor da linha da rota |
### `visibility`
| Opção | `true` | `false` |
| --------------------- | ------------------------------------ | ----------------------------------- |
| `requireVehicle` | Radar só aparece no veículo | Radar pode aparecer fora do veículo |
| `requireAccountLogin` | Radar só aparece após login na conta | Radar pode aparecer sem login |
***
## 5) `Config.Permissions`
Permissões de ações administrativas.
### `actions.teleport`
| Opção | `true` | `false` |
| --------- | ---------------------------------------------- | ----------------- |
| `enabled` | Ativa teleport no mapa para quem tem permissão | Desativa teleport |
`aclGroups`: lista de grupos ACL autorizados.
### `actions.administration`
| Opção | `true` | `false` |
| --------- | ------------------------------------- | -------------------------------- |
| `enabled` | Ativa funções administrativas do mapa | Desativa funções administrativas |
`aclGroups`: lista de grupos ACL autorizados.
***
## 6) `Config.Administration`
Configura recursos de administração no mapa.
| Opção | `true` | `false` |
| ------------------ | ----------------------------------------- | -------------------------- |
| `viewPlayersOnMap` | Mostra players no mapa para administração | Não mostra players |
| `markPvpZones` | Mostra marcação de zonas de PVP | Não mostra marcação de PVP |
`playerUpdateIntervalSeconds`:
* Valores recomendados: `1`, `10` ou `30`
* Menor valor = atualização mais rápida
***
## 7) `Config.CommonGroups`
Sistema de grupos compartilhados (ex.: polícia em serviço).
| Opção | `true` | `false` |
| -------------- | ------------------------------------------ | -------------------------- |
| `enabled` | Liga o sistema de grupos compartilhados | Desliga o sistema |
| `allowMapView` | Permite ver membros do mesmo grupo no mapa | Não mostra membros no mapa |
`syncIntervalSeconds`:
* Tempo de atualização dos grupos.
### `groups`
Cada grupo aceita:
* `id`: identificador interno único
* `name`: nome exibido
* `icon`: ícone usado no mapa
* `defaultState`:
* `true`: começa ativo por padrão
* `false`: começa desativado por padrão
* `aclGroups`: grupos ACL que pertencem a esse grupo (opcional)
* `elementDataKey`: chave de element data para vínculo (opcional)
* `elementDataValue`: valor necessário da element data (opcional)
***
## 8) `Config.Settings`
Controla o menu de ajustes que o jogador vê. Caso você não queira que o jogador possa editar alguma opção do mapa ou forçar alguma opção para todos os jogadores, é nessa seção que você faz isso.
Exemplo: Se você quiser que o mapa só tenha o tema claro e não seja possível mudar, você coloca `enabled = false` e `default = 'light'` na opção `theme`.
### Como funciona `options`
Cada opção tem:
* `enabled`
* `default`
Regra simples:
* `enabled = true`: jogador pode alterar no painel
* `enabled = false`: jogador não pode alterar, fica travado no `default`
### `options` completos
| Opção | Valores de `default` | Efeito |
| ---------------------------------- | ------------------------------------------------- | ------------------------------------------------ |
| `detailLevel` | `1` minimalista, `2` detalhado | Nível de detalhes de blips/informações |
| `mapQuality` | `1` performance, `2` intermediário, `3` qualidade | Qualidade do mapa grande |
| `minimapQuality` | `1` performance, `2` intermediário, `3` qualidade | Qualidade do minimapa |
| `viewInVehicle` | `true`/`false` | Define se o radar fica limitado a uso em veículo |
| `displayMode` | `1` (2D), `2` (3D) | Modo de exibição |
| `theme` | `'default'`, `'light'`, `'dark'` | Tema visual |
| `minimapPosition` | `1` a `9` | Posição na tela |
| `minimapFormat` | `1` circular, `2` retangular, `3` octagonal | Formato do minimapa |
| `minimapSize` | `0` a `1` | Tamanho do minimapa |
| `adminViewPlayersOnMap` | `true`/`false` | Padrão admin: ver players no mapa |
| `adminPlayerUpdateIntervalSeconds` | `1`, `10`, `30` | Padrão admin: intervalo de atualização |
| `adminMarkPvpZones` | `true`/`false` | Padrão admin: mostrar zonas de PVP |
### `detailLevel` (seção extra)
| Opção | O que muda |
| -------------------------- | -------------------------------------------------- |
| `keybind` | Tecla para alternar nível de detalhe |
| `enabled` | `true` ativa alternância no jogo, `false` desativa |
| `minimalBlipExclusionList` | Blips ocultados no modo minimalista |
| `hintActionWhenMinimal` | Texto da dica quando estiver no modo minimalista |
| `hintActionWhenDetailed` | Texto da dica quando estiver no modo detalhado |
***
## 9) `Config.Zones`
Cria zonas visíveis no mapa.
Campos por zona:
* `id`: identificador único
* `name`: nome da zona
* `owner`: dono/responsável (opcional)
* `color`: cor da zona (hex)
* `x`, `y`: posição inicial
* `width`, `height`: tamanho
* `renderMode`:
* `'blip'`: exibe com ícone
* `'name'`: exibe por nome
* `blipId`: ícone da zona (quando usar modo blip)
***
## 10) `Config.Markers`
Controla de onde os blips são lidos e como são exibidos.
### `source`
Valores aceitos:
* `'game_default'`: usa blips existentes do jogo
* `'element'`: usa nomes por element data do blip
* `'config'`: usa somente blips definidos no arquivo
* `'hybrid'`: mistura blips do jogo + blips da config
### Outras opções
| Opção | O que muda |
| ------------- | ------------------------------------------------------- |
| `elementKey` | Chave de element data usada para nome no modo `element` |
| `tracked` | Lista inicial de blips rastreados (opcional) |
| `customBlips` | Blips fixos criados direto na config |
| `labels` | Nome personalizado por ID de blip |
### `externalElementData`
| Opção | `true` | `false` |
| --------- | ------------------------------------------------- | --------------------------- |
| `enabled` | Permite pegar nome/ícone por element data externa | Ignora element data externa |
`nameKey`: chave da element data de nome.\
`iconKey`: chave da element data de ícone.
### `customBlips` (estrutura por item)
* `blipID`: ID do blip/ícone
* `name`: nome exibido
* `positions`: lista de posições `{x, y, z}`
***
## 11) `Config.PlayerTracking`
Rastreamento de jogadores por condição.
Cada rastreamento aceita:
* chave principal (nome da regra), exemplo: `['Assalto']`
* `elementValue`: valor que será verificado
* `aclsView`: grupos ACL que podem visualizar
* `icon`: ícone para o marcador do player
* `tint`: cor do marcador
***
## 12) `Config.Locations`
Personalização de nomes no mapa.
### `displayNames`
Tabela para renomear locais do GTA para nomes do seu servidor.
Exemplo:
```lua theme={null}
["Los Santos"] = "Manhattan"
```
### `citys`
Define posição de referência dos nomes de cidades no mapa.
### `neighborhoods`
Define posição de referência dos nomes de bairros/regiões no mapa.
Se você não quiser personalizar tudo, pode manter como está e editar só os nomes principais.
***
## Boas Práticas
* Altere uma seção por vez e teste no jogo.
* Use IDs de blip válidos para evitar ícones vazios.
* Em opções booleanas, lembre:
* `true` ativa
* `false` desativa
* Depois de salvar: `restart sqh_radar`
# Exports Whitelist System
Source: https://docs.squashcodes.com/pt/resources/whitelist-system/exports
Adquiriu o Whitelist System e está com dúvidas sobre as funções exportáveis? você está no lugar certo!
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Está com dúvidas de como configurar algo no sistema? Clique aqui
## Sobre o sistema
O Whitelist System é um sistema completo de entrada controlada para servidores MTA. Ele bloqueia o acesso de jogadores que ainda não passaram pelo processo de whitelist, com suporte a aplicação pelo jogo, pelo Discord ou pelos dois combinados.
Com as funções exportadas, você pode:
* Verificar manualmente se um player tem whitelist aprovada (útil ao trocar de personagem, reconectar, etc.);
* Aprovar um player na whitelist diretamente via script (útil para sistemas de staff, painéis administrativos, bots externos, etc.);
* Remover/resetar a whitelist de um player para que ele refaça o processo;
* Obter o Discord ID de um player que passou pela whitelist (útil para cruzar dados com sistemas de Discord).
## Funções Exportadas
### Server-side
* [verifyPlayerAccount](#verifyplayeraccount) -> `Verifica se o player tem whitelist e abre o painel caso não tenha`
* [approveWhitelistPlayer](#approvewhitelistplayer) -> `Aprova manualmente um player na whitelist`
* [removeWhitelistPlayer](#removewhitelistplayer) -> `Remove/reseta a whitelist de um player`
* [getPlayerDiscordID](#getplayerdiscordid) -> `Retorna o Discord ID do player (se disponível)`
***
## verifyPlayerAccount
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_whitelist']:verifyPlayerAccount(player)
```
**Required arguments**
* `player` (`player`): jogador a ser verificado.
**Comportamento**
* Consulta o banco de dados pelo serial do player.
* Se o status for `'approved'`, executa o callback `config.events.onJoinCity.server(player)` liberando o acesso.
* Se o status for diferente de `'approved'` (ou o player nunca fez whitelist), abre o painel de whitelist para ele.
* Esta função é chamada automaticamente nos eventos `onPlayerJoin` e `onPlayerLogin` quando `config.events.verifyOnJoin` ou `config.events.verifyOnLogin` são `true`. Use a export para chamadas manuais.
**Return**
* Não há retorno explícito. A ação ocorre via callbacks e triggers client-side.
**Example**
```lua theme={null}
-- SERVER-SIDE (chamar ao trocar de personagem)
addEventHandler('onCharacterSwitch', root, function(player)
exports['sqh_whitelist']:verifyPlayerAccount(player)
end)
```
```lua theme={null}
-- SERVER-SIDE (chamar via comando de staff para forçar re-verificação)
addCommandHandler('verificarwl', function(player, _, targetName)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_whitelist']:verifyPlayerAccount(target)
outputChatBox('Verificação enviada para ' .. targetName, player)
end
end)
```
***
## approveWhitelistPlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_whitelist']:approveWhitelistPlayer(player)
```
**Required arguments**
* `player` (`player`): jogador a ser aprovado.
**Comportamento**
* Atualiza o status na tabela `whitelist_players` para `'approved'`.
* Atualiza o status da tentativa (`whitelist_attempts`) com `aditionalInfos.approved_by = 'admin'`.
* Fecha o painel de whitelist do player e executa `config.events.onJoinCity.server(player)`.
* Se o player já estiver aprovado ou não tiver registro, envia uma notificação de erro.
**Return**
* Não há retorno explícito. O resultado é enviado via notificação ao player.
**Example**
```lua theme={null}
-- SERVER-SIDE (aprovação por comando de staff)
addCommandHandler('aprovarwl', function(player, _, targetName)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_whitelist']:approveWhitelistPlayer(target)
outputChatBox('Whitelist aprovada para ' .. getPlayerName(target), player)
else
outputChatBox('Jogador não encontrado.', player)
end
end)
```
```lua theme={null}
-- SERVER-SIDE (aprovação automática por sistema de entrevista próprio)
addEventHandler('onPlayerFinishInterview', root, function(player, approved)
if approved then
exports['sqh_whitelist']:approveWhitelistPlayer(player)
end
end)
```
***
## removeWhitelistPlayer
**Side:** `server`
**Syntax**
```lua theme={null}
exports['sqh_whitelist']:removeWhitelistPlayer(player)
```
**Required arguments**
* `player` (`player`): jogador que terá a whitelist removida/resetada.
**Comportamento**
* Remove o registro do player da tabela `whitelist_players`.
* Limpa os dados em memória do player (código de segurança, tentativa ativa, etc.).
* Após remover, chama `verifyPlayerAccount` automaticamente — o player verá o painel de whitelist novamente como se nunca tivesse feito.
* O histórico de tentativas (`whitelist_attempts`) **não** é apagado — apenas o vínculo do player é removido.
**Return**
* Não há retorno explícito. O player recebe uma notificação e o painel reabre.
**Example**
```lua theme={null}
-- SERVER-SIDE (remover whitelist por painel de admin)
addCommandHandler('removerwl', function(player, _, targetName)
local target = getPlayerFromName(targetName)
if target then
exports['sqh_whitelist']:removeWhitelistPlayer(target)
outputChatBox('Whitelist removida de ' .. getPlayerName(target), player)
else
outputChatBox('Jogador não encontrado.', player)
end
end)
```
***
## getPlayerDiscordID
**Side:** `server`
**Syntax**
```lua theme={null}
local discordID = exports['sqh_whitelist']:getPlayerDiscordID(player)
```
**Required arguments**
* `player` (`player`): jogador alvo.
**Comportamento**
* Retorna o Discord ID armazenado em cache para o player (preenchido no momento da aprovação via bot do Discord).
* O cache é carregado ao iniciar o resource (para players já online) e ao verificar a conta durante o `onPlayerLogin`/`onPlayerJoin`.
* Se o player não tiver passado pela whitelist via Discord, ou ainda não tiver sido verificado na sessão atual, retorna `false`.
**Return**
* `string` com o Discord ID do player, ex: `"123456789012345678"`.
* `false` se o Discord ID não estiver disponível.
**Example**
```lua theme={null}
-- SERVER-SIDE (cruzar com sistema de Discord)
addCommandHandler('meudiscord', function(player)
local discordID = exports['sqh_whitelist']:getPlayerDiscordID(player)
if discordID then
outputChatBox('Seu Discord ID: ' .. discordID, player)
else
outputChatBox('Seu Discord ID não foi encontrado.', player)
end
end)
```
```lua theme={null}
-- SERVER-SIDE (dar cargo via bot ao entrar)
addEventHandler('onPlayerLogin', root, function()
local discordID = exports['sqh_whitelist']:getPlayerDiscordID(source)
if discordID then
-- integrar com bot de discord externo
triggerEvent('onSyncDiscordRole', root, source, discordID, 'membro')
end
end)
```
***
## Observações
* Todas as exports só funcionam após o resource ser iniciado e a licença validada.
* A export `verifyPlayerAccount` é chamada automaticamente pelo sistema conforme as configurações `verifyOnJoin` e `verifyOnLogin`. Use a export para casos manuais específicos.
* Para aprovar players em lote ou por painel web, prefira usar `approveWhitelistPlayer` via script server-side no momento em que o player estiver online.
* O Discord ID só fica disponível no cache enquanto o player estiver online. Para consultas offline, acesse diretamente o banco de dados na coluna `discordID` da tabela `whitelist_players`.
# Configurações Whitelist System
Source: https://docs.squashcodes.com/pt/resources/whitelist-system/settings
Guia completo do config/settings.lua do Whitelist System.
## Resolva problemas comuns
Está com problemas para iniciar o seu produto? Clique aqui
Precisa integrar o Whitelist System com outro script? Clique aqui
## Sobre o sistema
O Whitelist System é um sistema completo de controle de acesso para servidores MTA. Ele bloqueia jogadores que não passaram pelo processo de whitelist, com suporte a aplicação pelo jogo, pelo Discord ou pelos dois combinados.
## Visão Geral
Este guia cobre **todo o arquivo** `config/settings.lua`.
Objetivo:
* Você entender exatamente o que cada opção muda.
* Você saber quando usar `true` ou `false`.
* Você configurar a whitelist sem precisar entrar em detalhes técnicos.
## Antes de Começar
* Arquivo de configuração: `config/settings.lua`
* Depois de alterar a config: reinicie o resource (`restart sqh_whitelist`)
* Regra geral:
* `true` = ativa a função
* `false` = desativa a função
***
## 1) `license`
Configuração da licença de ativação do sistema.
| Opção | Descrição |
| --------------- | ---------------------------------------------------------------- |
| `license.Email` | E-mail da conta na Squash Company utilizado na compra do produto |
| `license.Key` | Chave de licença do produto |
```lua theme={null}
license = {
["Email"] = "seu@email.com",
["Key"] = "SQUASH-xxxx-xxxx",
}
```
***
## 2) `config.infobox`
Funções de notificação do servidor. Configure aqui o sistema de alert/toast do seu servidor.
| Callback | Quando é chamado |
| -------- | --------------------------------------------------------------------------- |
| `server` | Notificações enviadas pelo lado server (recebe `source`, `message`, `type`) |
| `client` | Notificações enviadas pelo lado client (recebe `source`, `message`, `type`) |
`type` pode ser: `'success'`, `'error'`, `'info'`, `'warning'`
```lua theme={null}
config.infobox = {
['server'] = function(source, message, type)
exports["s_infobox"]:addInsInfobox(source, message, type)
end,
['client'] = function(source, message, type)
exports["s_infobox"]:addIncInfobox(message, type)
end,
}
```
***
## 3) `config.events`
### `onJoinCity`
Callbacks executados quando o player é **liberado** na whitelist (na entrada ou após aprovação).
```lua theme={null}
config.events.onJoinCity = {
['server'] = function(player)
-- ex.: liberar acesso ao servidor, remover freeze, abrir seletor de personagem
triggerClientEvent(player, 'abrirPersonagens', player)
end,
['client'] = function(player)
-- ex.: esconder HUD de whitelist, mostrar tela de boas-vindas
end
}
```
### Verificação automática
| Opção | `true` | `false` |
| --------------- | ---------------------------------------------------------------------------- | ------------------------ |
| `verifyOnJoin` | Verificar whitelist quando o player **entra no servidor** (`onPlayerJoin`) | Não verificar na entrada |
| `verifyOnLogin` | Verificar whitelist quando o player **faz login na conta** (`onPlayerLogin`) | Não verificar no login |
> **Recomendação**: Use `verifyOnLogin = true` e `verifyOnJoin = false` em servidores com sistema de login/conta próprio.
***
## 4) `config.social`
Links das redes sociais exibidos na tela de whitelist.
| Opção | Descrição |
| --------- | -------------------------------------- |
| `discord` | Link de convite do Discord do servidor |
| `youtube` | Link do canal do YouTube do servidor |
```lua theme={null}
config.social = {
discord = "https://discord.gg/seuservidor",
youtube = "https://youtube.com/seucanal",
}
```
***
## 5) `config.rules`
Link para o documento de regras do servidor, exibido na tela de whitelist.
```lua theme={null}
config.rules = "https://docs.google.com/document/d/..."
```
***
## 6) `config.getPlayerID`
Função que retorna o ID do jogador no seu sistema. Usada para registrar o `playerID` na tabela de whitelist.
```lua theme={null}
config.getPlayerID = function(player)
return getElementData(player, "ID") or math.random(1, 100000)
end
```
> Personalize para retornar o ID correto do seu sistema de contas/personagens.
***
## 7) `config.whitelistInfos`
### 7.1 Modo de aplicação
| Opção | Valor | Comportamento |
| ----------------- | ----- | ---------------------------------------------------------------------- |
| `whitelistOption` | `1` | O jogador faz a whitelist **somente pelo jogo** |
| `whitelistOption` | `2` | O jogador faz a whitelist pelo **Discord + jogo** (ambos obrigatórios) |
| `whitelistOption` | `3` | O jogador faz a whitelist **somente pelo Discord** |
***
### 7.2 `discordInfos` — Configurações do Bot Discord
Configurações usadas quando `whitelistOption` é `2` ou `3`.
| Opção | Descrição |
| ------------------------- | --------------------------------------------------------------------------------------------------- |
| `timeStartDiscord` | Tempo em minutos que o usuário tem para **começar** a responder a whitelist após o canal ser criado |
| `categoryWhitelists` | ID da categoria no Discord onde os canais de whitelist serão criados |
| `mentionInFormsView` | Lista de IDs de cargos que serão **marcados** na criação de um novo formulário |
| `discordChannelID` | ID do canal onde o bot envia a mensagem de início da whitelist |
| `discordChannelResponses` | ID do canal fórum onde os formulários respondidos são postados |
| `setRolesApproved` | Lista de IDs de cargos **dados** ao jogador quando **aprovado** |
| `setRolesReproved` | Lista de IDs de cargos **dados** ao jogador quando **reprovado** |
| `removeRolesApproved` | Lista de IDs de cargos **removidos** do jogador quando **aprovado** |
| `removeRolesReproved` | Lista de IDs de cargos **removidos** do jogador quando **reprovado** |
```lua theme={null}
discordInfos = {
timeStartDiscord = 5,
categoryWhitelists = '000000000000000000',
mentionInFormsView = {'000000000000000000'},
discordChannelID = '000000000000000000',
discordChannelResponses = '000000000000000000',
setRolesApproved = {'000000000000000000'},
setRolesReproved = {'000000000000000000'},
removeRolesApproved = {'000000000000000000'},
removeRolesReproved = {'000000000000000000'},
}
```
***
### 7.3 Comportamento das perguntas
| Opção | `true` | `false` |
| ---------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------- |
| `shuffleQuestions` | As perguntas aparecem em **ordem aleatória** | As perguntas aparecem na ordem definida |
| `backQuestion` | O jogador pode **voltar** à pergunta anterior | O jogador não pode voltar (no Discord nunca é permitido) |
| `timeToAnswerQuestion` | Cada pergunta tem um **tempo limite** para resposta | Sem limite de tempo por pergunta |
| `shuffleOptions` | As alternativas das perguntas `options` são **embaralhadas** | As alternativas aparecem na ordem definida |
| `automaticCorrection` | O sistema **corrige automaticamente** as respostas (questões `options` apenas) | A correção é feita **manualmente pelo staff** via Discord |
***
### 7.4 Chances e cooldown
| Opção | Tipo | Descrição |
| --------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `chancesToAnswer` | `number` | Quantidade de chances que o jogador tem para responder antes de entrar em cooldown |
| `cooldownTime` | `number` | Tempo de cooldown em **horas** após acabar as chances |
| `maximumWrongAnswers` | `number` | Quantidade máxima de respostas erradas permitidas (somente com `automaticCorrection = true`) |
> **Exemplo**: `chancesToAnswer = 3`, `cooldownTime = 24` — o jogador tem 3 tentativas e, ao esgotar, aguarda 24 horas para tentar novamente.
***
### 7.5 `translates` — Textos e mensagens do bot Discord
Textos exibidos pelo bot do Discord durante o processo de whitelist.
| Opção | Descrição |
| ------------------------- | ---------------------------------------------------------------------------------------- |
| `descriptionMainMessage` | Mensagem principal enviada no canal de início da whitelist (suporta Markdown do Discord) |
| `textButton` | Texto do botão de início |
| `emojiButton` | Emoji exibido no botão |
| `imageMain` | URL da imagem exibida na mensagem principal |
| `imageFooter` | URL da imagem do rodapé |
| `textFooter` | Texto do rodapé da mensagem |
| `startTitle` | Título da tela de início no canal do jogador |
| `startDescription` | Descrição da tela de início |
| `startButton` | Texto do botão para iniciar |
| `buttonApprove` | Texto do botão de aprovar (visível para o staff) |
| `buttonReprove` | Texto do botão de reprovar (visível para o staff) |
| `question_option_message` | Formato da mensagem de perguntas do tipo `options`. Use `$title`, `$endTime`, `$options` |
| `question_text_message` | Formato da mensagem de perguntas do tipo `text`. Use `$title`, `$endTime` |
***
### 7.6 `messages` — Mensagens operacionais
Mensagens enviadas em situações específicas do fluxo de whitelist.
| Chave | Quando é exibida |
| ----------------------- | ------------------------------------------------------------------ |
| `confirmInfos` | Ao solicitar confirmação de dados |
| `digitCode` | Ao pedir o código do jogo |
| `digitNameSurname` | Ao pedir nome e sobrenome |
| `max6Digits` | Quando o código digitado tem mais ou menos de 6 dígitos |
| `sended_solicitation` | Ao enviar a solicitação com sucesso |
| `code_incorrect` | Quando o código está errado |
| `register_success` | Após cadastrar a conta com sucesso |
| `name_unavailable` | Quando o nome escolhido já está em uso |
| `code_failed` | Quando ocorre falha na confirmação do código |
| `continue_in_game` | Quando o jogador deve continuar a whitelist no jogo |
| `continue_in_discord` | Quando o canal do Discord foi criado. Use `$channel` e `$time` |
| `start_minutes` | Contagem regressiva antes de iniciar as perguntas |
| `close_time_message` | Quando o tempo para iniciar a whitelist expirou. Use `$user` |
| `form_sended` | Quando o formulário foi enviado para avaliação. Use `$user` |
| `time_finish_answer` | Quando o tempo de resposta de uma pergunta esgota |
| `whitelist_exists` | Quando o jogador já tem uma whitelist em andamento. Use `$channel` |
| `whitelist_approved_dm` | Mensagem enviada por DM quando o jogador é **aprovado** |
| `whitelist_reproved_dm` | Mensagem enviada por DM quando o jogador é **reprovado** |
***
### 7.7 `questions` — Perguntas da whitelist
Lista de perguntas exibidas durante o processo. Cada pergunta é uma tabela com os seguintes campos:
| Campo | Tipo | Descrição |
| -------------- | -------- | ----------------------------------------------------------- |
| `title` | `string` | Texto da pergunta |
| `type` | `string` | `'text'` (resposta livre) ou `'options'` (múltipla escolha) |
| `timeResponse` | `number` | Tempo em segundos para responder |
| `options` | `table` | Lista de alternativas (somente para `type = 'options'`) |
Cada alternativa em `options`:
| Campo | Tipo | Descrição |
| ------------ | --------- | ------------------------------------------------------ |
| `nameOption` | `string` | Texto da alternativa |
| `isCorrect` | `boolean` | `true` para a resposta correta, `false` para incorreta |
> **Atenção**: Questões do tipo `'text'` **não** são corrigidas automaticamente, mesmo com `automaticCorrection = true`. Elas são sempre avaliadas pelo staff.
**Exemplo de pergunta `options`:**
```lua theme={null}
{
title = 'O que é PowerGaming?',
type = 'options',
timeResponse = 180,
options = {
{nameOption = 'Jogar com muito poder.', isCorrect = false},
{nameOption = 'Forçar ações irreais em outros jogadores.', isCorrect = true},
{nameOption = 'Usar cheats no servidor.', isCorrect = false},
}
}
```
**Exemplo de pergunta `text`:**
```lua theme={null}
{
title = 'Descreva brevemente a história do seu personagem.',
type = 'text',
timeResponse = 120,
}
```
***
## 8) `config.musicPlayer`
Lista de músicas tocadas na tela de whitelist. Cada item é uma tabela com os campos:
| Campo | Descrição |
| -------- | ----------------------- |
| `name` | Nome da música |
| `author` | Nome do artista |
| `url` | URL de stream da música |
```lua theme={null}
config.musicPlayer = {
{name = "Mistérios", author = "Kayblack", url = "https://server1.mtabrasil.com.br/play?id=..."},
}
```
***
## 9) `config.faq`
Lista de perguntas frequentes exibidas na tela de whitelist antes de o jogador iniciar.
Cada item é uma tabela com:
| Campo | Descrição |
| -------- | -------------------------- |
| `topic` | Título/pergunta do FAQ |
| `answer` | Resposta exibida ao clicar |
```lua theme={null}
config.faq = {
{
topic = 'O que é Roleplay (RP)?',
answer = 'Roleplay é...'
},
}
```
***
## 10) `config.nameMainConfigs`
Configuração auxiliar para obter o nome da conta interna do sistema (usado para configuração técnica de HTTP com serial).
| Opção | Tipo | Descrição |
| ---------------- | ------------------ | ------------------------------------------------------------------------------------------------------- |
| `commandActive` | `boolean` | Ativa o comando `/vernomedaconta` no jogo. Deixe `true` apenas durante a configuração inicial do serial |
| `havePermission` | `function(player)` | Retorna `true` se o player tem permissão para usar o comando |
> **Importante**: Após usar o comando para configurar o serial, desative esta opção com `commandActive = false`.
```lua theme={null}
config.nameMainConfigs = {
commandActive = false,
havePermission = function(player)
return isObjectInACLGroup('user.'..getAccountName(getPlayerAccount(player)), aclGetGroup('Admin'))
end
}
```
***
## 11) `interface`
Configurações visuais da interface de whitelist.
### 11.1 Cores
| Opção | Descrição |
| ------------------------ | --------------------------------------------------- |
| `white` | Cor branca base |
| `black` | Cor preta base |
| `primary` | Cor principal do servidor (botões, destaques, etc.) |
| `primary_contrast` | Cor de texto sobre a cor primária |
| `primary_2` | Variação mais clara da cor primária |
| `primary_element` | Cor de fundo de elementos com baixa opacidade |
| `primary_element_border` | Cor de borda de elementos com opacidade média |
| `hover_element_border` | Cor de borda ao passar o mouse |
| `primary_text` | Cor principal de texto |
| `secondary_text` | Cor de texto secundário (40% de opacidade) |
| `tertiary_text` | Cor de texto terciário (30% de opacidade) |
| `question_title` | Cor do título das perguntas (60% de opacidade) |
| `inactive_text` | Cor de texto inativo (10% de opacidade) |
| `red_wrong` | Cor vermelha para respostas erradas |
| `red_wrong_contrast` | Cor do texto sobre o fundo vermelho |
| `warning` | Cor amarela para avisos |
| `warning_contrast` | Cor do texto sobre o fundo amarelo |
| `modal_bg` | Cor de fundo do modal/painel |
Formato das cores: `'#RRGGBB XX%'` onde `XX%` é a opacidade.
```lua theme={null}
interface.colors = {
primary = '#198028 100%', -- cor principal do servidor
primary_contrast = '#FFFFFF 100%',
modal_bg = '#0E0E0E 98%',
}
```
### 11.2 Border Radius
| Opção | Tipo | Descrição |
| --------------- | ------------- | ------------------------------------------------------------------- |
| `border-radius` | `number` (px) | Arredondamento dos botões, caixas de texto e elementos da interface |
```lua theme={null}
interface['border-radius'] = 30
```
***
## 12) `translate`
Define o idioma padrão e os textos da interface.
### 12.1 Idioma padrão
| Opção | Valor | Descrição |
| -------------------- | --------- | --------------------- |
| `translate.language` | `'PT-BR'` | Português do Brasil |
| `translate.language` | `'EN'` | Inglês |
| `translate.language` | `'PT-PT'` | Português de Portugal |
| `translate.language` | `'ES'` | Espanhol |
| `translate.language` | `'TR'` | Turco |
| `translate.language` | `'RU'` | Russo |
| `translate.language` | `'HU'` | Húngaro |
```lua theme={null}
translate = {
language = 'PT-BR',
}
```
### 12.2 Campos por idioma
Cada bloco de idioma contém:
| Campo | Descrição |
| ---------------------- | ------------------------------------------------------------------------------ |
| `months` | Nomes dos meses por extenso |
| `date_format` | Formato de data completo (usa `string.format` do Lua) |
| `hours_format` | Formato de horas e minutos (usado no cooldown) |
| `date_format_short` | Formato curto de data |
| `question_definitions` | Letras usadas para identificar alternativas (`{"A", "B", "C", "D", "E", "F"}`) |
***
## Dicas Finais
* Após qualquer alteração no `config/settings.lua`, reinicie o resource com `restart sqh_whitelist`.
* Ao configurar pela primeira vez, ative `nameMainConfigs.commandActive = true`, use o comando `/vernomedaconta` para obter o nome da conta, configure o serial no painel da Squash e depois volte `commandActive = false`.
* Para servidores com login próprio, use `verifyOnLogin = true` e `verifyOnJoin = false` para evitar verificação prematura antes do login.
* Configure o `config.events.onJoinCity.server` para liberar o acesso do player ao servidor após a whitelist ser aprovada — sem isso o jogador será aprovado mas não terá o acesso liberado pelo seu sistema.
# Configuração Inicial
Source: https://docs.squashcodes.com/pt/start
Comprou seu primeiro resource e não sabe como ligar o resource? veja agora.
Esse passo deve ser repetido para TODOS os produtos da sua conta, você precisa configurar todos da mesma maneira, inclusive colocar o ip em cada um no SITE.
* [Tutorial Em Vídeo](#tutorial-em-video) --> `Veja como ligar o resource através de um vídeo`
* [Tutorial Em Texto](#tutorial-em-texto) --> `Veja como ligar o resource passo a passo de maneira escrita`
* [Erros comuns](#erros-comuns) --> `Veja como resolver possíveis erros ao iniciar o resource`
# Tutorial Em vídeo
# Tutorial Em Texto
## Passo 1
A primeira coisa que você deve fazer é acessar nosso [SITE](https://www.squashcodes.com) e entrar na sua conta clicando em **"Área do Cliente"** no canto superior direito, após isso você deverá acessar as **configurações** da sua conta que fica no canto superior direito, como na imagem abaixo:
Após isso, você deverá procurar por **Gerenciar licenças**, essa opção fica um pouco abaixo do nome da sua conta, como no exemplo abaixo:
Após isso você terá um painel com todas suas licenças, você deverá escolher o produto que você deseja alterar o IP e vai colocar o IP no campo demonstrado abaixo:
### Como pegar o IP?
#### Host
Basta você entrar no seu MTA, escolher o seu servidor na lista de servidores e copiar o IP que fica logo acima, como demonstrado abaixo:
#### Servidor Local
Você terá que entrar nesse [SITE](https://www.squashcodes.com), após entrar você vai copiar o IP que aparecer, depois você vai no seu MTA e pega a porta, então o passo é simples:
IP DO SITE:PORTA DO MTA
## Passo 2
Agora que você já colocou o seu IP no site, você deverá fazer a configuração dentro do script, para isso continue no mesmo painel de **GERENCIAR LICENÇAS**
Abra o arquivo de configuração do seu produto, normalmente dentro de uma pasta chamada "config" com o nome "main.lua" ou "config.lua", a primeira linha deverá ser assim:
```lua theme={null}
license = {
["Email"] = "",
["Key"] = "",
}
```
Agora basta você preencher as informações DENTRO das aspas "", a KEY você deverá pegar no site do GERENCIAR LICENÇAS, como no exemplo abaixo:
Por fim, seu arquivo de configuração deverá ficar da seguinte forma:
```lua theme={null}
license = {
["Email"] = "support@squashcodes.com",
["Key"] = "SQUASH-2020-2020",
}
```
Caso mesmo assim o seu produto não inicie corretamente, recomendamos que você abra um ticket em nosso canal do [discord](https://discord.gg/XFfKTDF3ak) para que possamos auxiliar da melhor forma
# Erros comuns
#### getServerIpFromMasterServer
```
attempt to call global 'getServerIpFromMasterServer' (a nil value)
```
Caso apareça esse erro ao ligar um de nossos produtos, você deve atualizar o seu servidor do MTA para a ultima versão, ou qualquer versão acima de: **1.6.0 r22890**
**Porque esse erro acontece?**
Essa função é uma função extremamente nova no MTA, então é possível que seu servidor ainda não esteja atualizado para recebê-la.
### Caso você não saiba como atualizar, entre em contato com sua HOSPEDAGEM para que eles atualizem para você.
# Obter Suporte
Source: https://docs.squashcodes.com/pt/support
Está precisando de uma ajuda diretamente com um de nossos atendentes? aqui você verá como solicitar um suporte de maneira adequada
### Passo 1:
Todos nossos atendimentos são feitos via discord, portanto você deve [CLICAR AQUI](https://discord.gg/XFfKTDF3ak) para entrar em nosso discord, caso não esteja
### Passo 2:
Agora que você já está em nosso discord, você deverá procurar por um canal em nossa lista chamado **🎫・ticket**, ele fica em uma categoria chamada **SUPPORT**, como na print abaixo:
Agora basta clicar em um botão para abrir um atendimento, caso você não tenha tag de cliente em nosso site abra um ticket enviando print dos produtos no site em tela cheia.
**OBS:** Recomendamos que você veja o F.A.Q primeiro antes de abrir um atendimento, pois sua dúvida pode ter sido respondida já.
# Termos de compra
Source: https://docs.squashcodes.com/pt/terms
Está querendo comprar um produto mas não sabe das obrigações da parte consumidora e fornecedora? você está no lugar certo.
## OBJETIVO DOS TERMOS E CONDIÇÕES DE USO
Este texto trata-se dos termos de compra e venda entre fornecedor e consumidor respaldados inteiramente pelo presente Código de Proteção e Defesa do Consumidor. Recomenda-se a leitura de maneira integral.
Por favor, leia atentamente os Termos de uso, Compra e Responsabilidade, pois o mesmo é o contrato que regulará a conduta no uso deste site. Ao utilizar a loja virtual da Squash Codes, você estará aderindo a todos os seus termos e concordando, expressamente, com as condições previstas para a sua utilização.
## DA PARTE FORNECEDORA
* Fica estipulado que a loja Squash Codes será a parte fornecedora.
## DA PARTE CONSUMIDORA
* Fica estipulado que denomina-se consumidor, qualquer cidadão que efetuar a compra devidamente legalizada nos domínios da loja Squash Codes.
* Fica estipulado que ao comprar qualquer produto em nossa loja, a revenda do mesmo é proibida, podendo ocasionar na perda do produto.
DAS OBRIGAÇÕES
* Pela parte FORNECEDORA fica a critério ÚNICO E EXCLUSIVAMENTE ARBITRÁRIO a disposição dos produtos no site, por não se tratar de loja física.
* É de obrigação da parte FORNECEDORA prestar todo o auxílio para a parte CONSUMIDORA dentro dos horários comerciais: Seg à Sex das 12:00 às 18:00 e Sábado e Domingo das 10:00 às 18:00 ficando a critério da loja Squash Codes o atendimento fora do horário estipulado.
* É de obrigação da parte CONSUMIDORA informar com clareza e de forma fidedigna as indagações da parte FORNECEDORA em eventual dano ou vício do produto.
* É de obrigação da parte CONSUMIDORA arcar com qualquer taxa aplicada nos sites usados para conclusão de pagamento. Devendo a parte FORNECEDORA informar sobre possíveis taxas.
DA POLÍTICA DE REEMBOLSO
* Conforme Art 49, Parágrafo único do Código de Proteção e Defesa do Consumidor fica expressamente avisado que por não se tratar de loja física, o REEMBOLSO não será EFETUADO, ficando a critério da parte FORNECEDORA analisar de BOA FÉ a real necessidade.
* Conforme Art 26, II do Código de Proteção e Defesa do Consumidor ao se apresentar um vicio no produto pela parte CONSUMIDORA fica na responsabilidade da parte FORNECEDORA saná-lo em até 90 dias.
## DAS PENALIDADES
* Fica obrigatório a parte FORNECEDORA a oferecer as opções de ressarcimento a parte CONSUMIDORA se no período de 30 dias o vício não for sanado, conforme ampla extensão do Art 38 do Código de Proteção e Defesa do Consumidor.
* Fica estipulado que a parte CONSUMIDORA ao agir de MÁ FÉ para obter vantagem indevida, perderá o acesso aos produtos da loja Squash Codes e não poderá solicitar REEMBOLSO.
## ALTERAÇÕES NOS TERMOS DE USO
Reservamo-nos o direito de modificar, não continuar ou terminar este site a qualquer momento, ou modificar os Termos de Uso ao nosso único e exclusivo critério, sem qualquer obrigatoriedade de notificação.
## INFORMAÇÕES DE PRIVACIDADE
Garantimos ao usuário deste site o sigilo de todos os dados fornecidos. Comprometemo-nos a não fornecer seu e-mail ou dados pessoais para terceiros. Para mais informações, consulte a coluna de "Política de privacidade"
## INFORMAÇÕES DE CADASTRO
O cadastro é necessário para a realização de compras neste site. Desde já, fica acordado que os dados pessoais fornecidos no cadastro eletrônico são verdadeiros e próprios, e que você responderá por todos os prejuízos e/ou perdas que a falsidade das informações possa implicar.
## INFORMAÇÕES DE PAGAMENTOS
Para sua segurança, facilidade de uso e comodidade utilizamos o intermediador de pagamentos MercadoPago ou PayPal, portanto o responsável por seu pagamento conosco é este, sendo dessa forma não nos responsabilizamos por transações não aprovadas pelo MercadoPago ou PayPal. Pagamentos feitos diretamente em nossas contas, serão administrados por nossa empresa e serão de nossa responsabilidade, qualquer divergência poderá ser tratada em um de nossos canais de atendimento.
## CONDUTA NO SITE
Ao acessar a loja virtual da Squash Codes, o usuário se compromete a não enviar, carregar ou transmitir qualquer material que contenha códigos ou vírus, bem como a não utilizar identidade falsa e a não se conduzir de maneira vulgar, inadequada ou ofensiva enquanto se utilizar deste serviço, sob pena de remoção permanente do conteúdo considerado inadequado aos termos ou cancelamento imediato da conta, sem prejuízo de responsabilização pelas eventuais perdas e danos causados.
## LINKS PARA OUTROS SITES
Você pode encontrar links para outros sites que não são da Squash Codes nesta loja virtual. Estes links existem com propósito informativo. A Squash Codes não é responsável por atualizar o conteúdo destes sites. Além disso, links para outras páginas de empresas, assim como seus produtos e/ou serviços da web, não são de propriedade ou aprovados por parte da Squash Codes.
## ISENÇÃO DE RESPONSABILIDADE
Em nenhum momento a loja virtual Squash Codes e seus adjacentes (seus sócios, administradores ou empregados) estarão sujeitos a você por qualquer dano incluindo limitação indireta, incidental, especial, punitiva ou consequencial vindo de conexão com seu uso da loja virtual, conteúdo deste site e arbitrariedades dos usuários, sendo ou não avisado da possibilidade de tal dano. Você também concorda em defender, indenizar e manter a Squash Codes e seus adjacentes sem quaisquer prejuízos ou reclamações, obrigações, danos, perdas e gastos incluindo sem limitação das taxas e custas do advogado vindas ou de alguma forma ligadas ao (I) seu acesso ou uso do site, serviços, conteúdo do site e arbitrariedade do usuário; (II) sua violação destes termos de uso; (III) sua violação do direito de terceiros, incluindo qualquer direito de propriedade intelectual, propriedade ou direito privado; ou (IV) qualquer reivindicação de que uma de suas arbitrariedades do usuário tenha causado dano a terceiros.
## POLÍTICA DE PRIVACIDADE
A Squash Codes garante segurança e privacidade de identidade aos internautas que fazem compras na loja virtual. Dados cadastrados como nome, endereço e são protegidos por sistemas avançados de criptografia enquanto são enviados, e mantidos em sigilo em servidores seguros da squashcodes.com
NÃO armazenamos dados financeiros como números de cartões. Todo o nosso sistema de pagamento é realizado por empresas de pagamento terceirizadas
O site da Squash Codes tem adotado os níveis legalmente requeridos quanto à segurança na proteção de dados, tendo instalado todos os meios e medidas técnicas ao seu alcance para evitar a perda, mau uso, alteração, acesso não autorizado ou subtração indevida dos Dados Pessoais recolhidos. Não obstante, o usuário deve estar ciente de que as medidas de segurança relativas à Internet não são integralmente infalíveis.
A Squash Codes reserva-se o direito de modificar a presente política para adaptá-la a alterações legislativas ou jurisprudências, ou aquelas relativas às práticas comerciais. Em qualquer caso, a Squash Codes anunciará no site, por meio desta página, as mudanças introduzidas com uma antecedência razoável à sua colocação em prática.
Ao se cadastrar, os clientes determinam voluntariamente que desejam fornecer os seus Dados Pessoais requeridos na contratação, atualização ou cancelamento de determinados serviços oferecidos no site ou através dele, tais como: adesão ao Programa Fidelidade, compras na loja virtual, contatos com os serviços de atendimento e outros.
Os dados pessoais recolhidos pela Squash Codes serão objeto de tratamento automatizado, sendo incorporados aos correspondentes registros eletrônicos de dados pessoais, dos quais a Squash Codes será titular e responsável. Os dados obtidos e utilizados pela Squash Codes, bem como pelos parceiros contratados pela Squash Codes para os serviços oferecidos no site fazem parte dessa política.
As informações pessoais fornecidas pelos clientes são utilizadas com o propósito básico de identificar o público usuário, seu perfil e hábitos de compra, para gestão, administração, atendimento, ampliação e melhorias nos produtos e serviços oferecidos; também para a adequação dos serviços às preferências e gostos dos usuários, para a criação de novos produtos e serviços, para o envio de informações operacionais e comerciais relativas aos produtos e serviços, por meios tradicionais e/ou eletrônicos.
## DAS DISPOSIÇÕES FINAIS
* Fica-se expressamente avisado que a loja Squash Codes possui todos os direitos reservados.