DRS Advanced Mechanics
Sistema de mecânico completo, feito de raiz. Há oficinas self-service (o jogador paga e modifica) e oficinas de empresa (com empregados, cargos, saldo e o job do framework), todas criadas e editadas em jogo pelo menu de staff. O Customs tem pré-visualização ao vivo e câmara orbital. O script inclui ainda:
- reparações com minijogo e animações de trabalho;
- quilometragem e desgaste de 10 peças, que mexe no handling do carro;
- tuning de motor, turbo, tração, caixa, pneus e travões;
- stance, nitro com chamas e purga, controlador de luzes, dinamómetro e elevador;
- encomendas de peças, fornecedores com vendedor, armazém, faturas com comissão e anúncios;
- um tablet com 9 aplicações.
Funciona com Qbox, QBCore e ESX.
#Requisitos
| Recurso | Obrigatório |
|---|---|
oxmysql | Sim |
| Qbox, QBCore ou ESX | Sim (deteção automática) |
ox_inventory ou qb-inventory | Sim (peças, kits e armazém) |
qb-banking, qb-management ou Renewed-Banking | Não — só com Config.UseFrameworkJobs = true (conta da empresa no banco) |
Nota
Não precisa do ox_lib. Se tinhas outro mecânico (ex.: jg-mechanic ou qb-mechanicjob), desliga-o antes de ligar este.
#Instalação
- Coloca
drs_mechanicemresources. - Adiciona ao
server.cfg, depois da framework e do inventário:
ensure oxmysql
ensure qb-core
ensure qb-inventory
ensure drs_mechanic- As tabelas são criadas sozinhas no primeiro arranque (também estão em
sql/drs_mechanic.sql). - Cria os itens (ver abaixo) e copia as imagens de
install/images/para o teu inventário. - Dá acesso ao menu de staff (os grupos de admin da framework já têm):
add_ace group.admin drs.mechanic allow- Em jogo, abre o
/mecanicoadmine cria ou ajusta as oficinas.
#Itens
Importante
Tens de criar o item tablet_mecanico no teu inventário. Sem ele, o tablet só abre com o comando /tablet. Copia a linha do item (está nas listas de baixo) e a imagem install/images/tablet_mecanico.png (podes usar a imagem do tablet que já tens no inventário). O nome do item muda-se em Config.Tablet.item, que também aceita uma lista, por exemplo { 'tablet_mecanico', 'mechanic_tablet' } se já tinhas um item de tablet.
tablet_mecanico = { name = 'tablet_mecanico', label = 'Tablet de mecânico', weight = 800, type = 'item', image = 'tablet_mecanico.png', unique = true, useable = true, shouldClose = true, description = 'Tablet da oficina' },QBCore — dentro de qb-core/shared/items.lua:
-- drs_mechanic: cola dentro de qb-core/shared/items.lua (drs-core: drs-core/shared/items.lua)
-- Imagens: copia install/images/*.png para a pasta de imagens do inventário (qb-inventory/html/images/)
advancedrepairkit = { name = 'advancedrepairkit', label = 'Kit de reparação avançado', weight = 4000, type = 'item', image = 'advancedrepairkit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Reparação completa (mecânicos)' },
air_filter = { name = 'air_filter', label = 'Filtro de ar', weight = 400, type = 'item', image = 'air_filter.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
awd_drivetrain = { name = 'awd_drivetrain', label = 'Tração integral', weight = 15000, type = 'item', image = 'awd_drivetrain.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
brakepad_set = { name = 'brakepad_set', label = 'Jogo de pastilhas', weight = 1500, type = 'item', image = 'brakepad_set.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
ceramic_brakes = { name = 'ceramic_brakes', label = 'Travões cerâmicos', weight = 5000, type = 'item', image = 'ceramic_brakes.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
cleaningkit = { name = 'cleaningkit', label = 'Kit de limpeza', weight = 800, type = 'item', image = 'cleaningkit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Limpa o veículo' },
clutch = { name = 'clutch', label = 'Embraiagem', weight = 3000, type = 'item', image = 'clutch.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
empty_nitrous_bottle = { name = 'empty_nitrous_bottle', label = 'Garrafa de nitro vazia', weight = 1500, type = 'item', image = 'empty_nitrous_bottle.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
engine_oil = { name = 'engine_oil', label = 'Óleo do motor', weight = 1000, type = 'item', image = 'engine_oil.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
ev_battery = { name = 'ev_battery', label = 'Bateria elétrica', weight = 9000, type = 'item', image = 'ev_battery.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
ev_coolant = { name = 'ev_coolant', label = 'Refrigerante elétrico', weight = 1000, type = 'item', image = 'ev_coolant.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
ev_engine = { name = 'ev_engine', label = 'Motor elétrico de performance', weight = 25000, type = 'item', image = 'ev_engine.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
ev_motor = { name = 'ev_motor', label = 'Motor elétrico', weight = 12000, type = 'item', image = 'ev_motor.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
fwd_drivetrain = { name = 'fwd_drivetrain', label = 'Tração dianteira', weight = 10000, type = 'item', image = 'fwd_drivetrain.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
gearbox_6 = { name = 'gearbox_6', label = 'Caixa de 6 velocidades', weight = 12000, type = 'item', image = 'gearbox_6.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
gearbox_8 = { name = 'gearbox_8', label = 'Caixa de 8 velocidades', weight = 14000, type = 'item', image = 'gearbox_8.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
i4_engine = { name = 'i4_engine', label = 'Motor I4 turbo', weight = 20000, type = 'item', image = 'i4_engine.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
lighting_controller = { name = 'lighting_controller', label = 'Controlador de luzes', weight = 500, type = 'item', image = 'lighting_controller.png', unique = true, useable = true, shouldClose = true, combinable = nil, description = 'Usa dentro do carro' },
tablet_mecanico = { name = 'tablet_mecanico', label = 'Tablet de mecânico', weight = 800, type = 'item', image = 'tablet_mecanico.png', unique = true, useable = true, shouldClose = true, combinable = nil, description = 'Tablet da oficina' },
nitrous_bottle = { name = 'nitrous_bottle', label = 'Garrafa de nitro', weight = 3000, type = 'item', image = 'nitrous_bottle.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Enche o nitro do carro' },
nitrous_install_kit = { name = 'nitrous_install_kit', label = 'Kit de instalação de nitro', weight = 5000, type = 'item', image = 'nitrous_install_kit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
offroad_tyres = { name = 'offroad_tyres', label = 'Pneus todo-o-terreno', weight = 9000, type = 'item', image = 'offroad_tyres.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
repairkit = { name = 'repairkit', label = 'Kit de reparação', weight = 2500, type = 'item', image = 'repairkit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Repara o motor e a carroçaria' },
rwd_drivetrain = { name = 'rwd_drivetrain', label = 'Tração traseira', weight = 12000, type = 'item', image = 'rwd_drivetrain.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
slick_tyres = { name = 'slick_tyres', label = 'Pneus slick', weight = 8000, type = 'item', image = 'slick_tyres.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
spark_plug = { name = 'spark_plug', label = 'Vela', weight = 80, type = 'item', image = 'spark_plug.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
stancer_kit = { name = 'stancer_kit', label = 'Kit de stance', weight = 4000, type = 'item', image = 'stancer_kit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
suspension_parts = { name = 'suspension_parts', label = 'Peças de suspensão', weight = 6000, type = 'item', image = 'suspension_parts.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
turbo_kit = { name = 'turbo_kit', label = 'Kit turbo', weight = 6000, type = 'item', image = 'turbo_kit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
tyre_set = { name = 'tyre_set', label = 'Jogo de pneus', weight = 8000, type = 'item', image = 'tyre_set.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
tyrekit = { name = 'tyrekit', label = 'Kit de pneus', weight = 1500, type = 'item', image = 'tyrekit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Repara os pneus' },
v12_engine = { name = 'v12_engine', label = 'Motor V12', weight = 38000, type = 'item', image = 'v12_engine.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },
v8_engine = { name = 'v8_engine', label = 'Motor V8', weight = 30000, type = 'item', image = 'v8_engine.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Peça de oficina' },ox_inventory / Qbox — dentro de ox_inventory/data/items.lua:
-- drs_mechanic: cola dentro de ox_inventory/data/items.lua
-- Imagens: copia install/images/*.png para ox_inventory/web/images/
['advancedrepairkit'] = { label = 'Kit de reparação avançado', weight = 4000, stack = true, close = true, description = 'Reparação completa (mecânicos)', client = { image = 'advancedrepairkit.png' } },
['air_filter'] = { label = 'Filtro de ar', weight = 400, stack = true, close = true, description = 'Peça de oficina', client = { image = 'air_filter.png' } },
['awd_drivetrain'] = { label = 'Tração integral', weight = 15000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'awd_drivetrain.png' } },
['brakepad_set'] = { label = 'Jogo de pastilhas', weight = 1500, stack = true, close = true, description = 'Peça de oficina', client = { image = 'brakepad_set.png' } },
['ceramic_brakes'] = { label = 'Travões cerâmicos', weight = 5000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'ceramic_brakes.png' } },
['cleaningkit'] = { label = 'Kit de limpeza', weight = 800, stack = true, close = true, description = 'Limpa o veículo', client = { image = 'cleaningkit.png' } },
['clutch'] = { label = 'Embraiagem', weight = 3000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'clutch.png' } },
['empty_nitrous_bottle'] = { label = 'Garrafa de nitro vazia', weight = 1500, stack = true, close = true, description = 'Peça de oficina', client = { image = 'empty_nitrous_bottle.png' } },
['engine_oil'] = { label = 'Óleo do motor', weight = 1000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'engine_oil.png' } },
['ev_battery'] = { label = 'Bateria elétrica', weight = 9000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'ev_battery.png' } },
['ev_coolant'] = { label = 'Refrigerante elétrico', weight = 1000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'ev_coolant.png' } },
['ev_engine'] = { label = 'Motor elétrico de performance', weight = 25000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'ev_engine.png' } },
['ev_motor'] = { label = 'Motor elétrico', weight = 12000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'ev_motor.png' } },
['fwd_drivetrain'] = { label = 'Tração dianteira', weight = 10000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'fwd_drivetrain.png' } },
['gearbox_6'] = { label = 'Caixa de 6 velocidades', weight = 12000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'gearbox_6.png' } },
['gearbox_8'] = { label = 'Caixa de 8 velocidades', weight = 14000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'gearbox_8.png' } },
['i4_engine'] = { label = 'Motor I4 turbo', weight = 20000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'i4_engine.png' } },
['lighting_controller'] = { label = 'Controlador de luzes', weight = 500, stack = false, close = true, description = 'Usa dentro do carro', client = { image = 'lighting_controller.png' } },
['tablet_mecanico'] = { label = 'Tablet de mecânico', weight = 800, stack = false, close = true, description = 'Tablet da oficina', client = { image = 'tablet_mecanico.png' } },
['nitrous_bottle'] = { label = 'Garrafa de nitro', weight = 3000, stack = true, close = true, description = 'Enche o nitro do carro', client = { image = 'nitrous_bottle.png' } },
['nitrous_install_kit'] = { label = 'Kit de instalação de nitro', weight = 5000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'nitrous_install_kit.png' } },
['offroad_tyres'] = { label = 'Pneus todo-o-terreno', weight = 9000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'offroad_tyres.png' } },
['repairkit'] = { label = 'Kit de reparação', weight = 2500, stack = true, close = true, description = 'Repara o motor e a carroçaria', client = { image = 'repairkit.png' } },
['rwd_drivetrain'] = { label = 'Tração traseira', weight = 12000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'rwd_drivetrain.png' } },
['slick_tyres'] = { label = 'Pneus slick', weight = 8000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'slick_tyres.png' } },
['spark_plug'] = { label = 'Vela', weight = 80, stack = true, close = true, description = 'Peça de oficina', client = { image = 'spark_plug.png' } },
['stancer_kit'] = { label = 'Kit de stance', weight = 4000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'stancer_kit.png' } },
['suspension_parts'] = { label = 'Peças de suspensão', weight = 6000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'suspension_parts.png' } },
['turbo_kit'] = { label = 'Kit turbo', weight = 6000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'turbo_kit.png' } },
['tyre_set'] = { label = 'Jogo de pneus', weight = 8000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'tyre_set.png' } },
['tyrekit'] = { label = 'Kit de pneus', weight = 1500, stack = true, close = true, description = 'Repara os pneus', client = { image = 'tyrekit.png' } },
['v12_engine'] = { label = 'Motor V12', weight = 38000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'v12_engine.png' } },
['v8_engine'] = { label = 'Motor V8', weight = 30000, stack = true, close = true, description = 'Peça de oficina', client = { image = 'v8_engine.png' } },ESX — importa na base de dados:
-- drs_mechanic: itens para ESX (es_extended)
INSERT IGNORE INTO `items` (`name`, `label`, `weight`) VALUES
('advancedrepairkit', 'Kit de reparação avançado', 4),
('air_filter', 'Filtro de ar', 1),
('awd_drivetrain', 'Tração integral', 15),
('brakepad_set', 'Jogo de pastilhas', 1),
('ceramic_brakes', 'Travões cerâmicos', 5),
('cleaningkit', 'Kit de limpeza', 1),
('clutch', 'Embraiagem', 3),
('empty_nitrous_bottle', 'Garrafa de nitro vazia', 1),
('engine_oil', 'Óleo do motor', 1),
('ev_battery', 'Bateria elétrica', 9),
('ev_coolant', 'Refrigerante elétrico', 1),
('ev_engine', 'Motor elétrico de performance', 25),
('ev_motor', 'Motor elétrico', 12),
('fwd_drivetrain', 'Tração dianteira', 10),
('gearbox_6', 'Caixa de 6 velocidades', 12),
('gearbox_8', 'Caixa de 8 velocidades', 14),
('i4_engine', 'Motor I4 turbo', 20),
('lighting_controller', 'Controlador de luzes', 1),
('tablet_mecanico', 'Tablet de mecânico', 1),
('nitrous_bottle', 'Garrafa de nitro', 3),
('nitrous_install_kit', 'Kit de instalação de nitro', 5),
('offroad_tyres', 'Pneus todo-o-terreno', 9),
('repairkit', 'Kit de reparação', 2),
('rwd_drivetrain', 'Tração traseira', 12),
('slick_tyres', 'Pneus slick', 8),
('spark_plug', 'Vela', 1),
('stancer_kit', 'Kit de stance', 4),
('suspension_parts', 'Peças de suspensão', 6),
('turbo_kit', 'Kit turbo', 6),
('tyre_set', 'Jogo de pneus', 8),
('tyrekit', 'Kit de pneus', 1),
('v12_engine', 'Motor V12', 38),
('v8_engine', 'Motor V8', 30);#Oficinas
#Self-service e empresa
- Self-service: qualquer jogador leva o carro ao lugar de trabalho, abre o Customs ou repara, e paga do bolso (com o desconto
Config.SelfServiceDiscount). - Empresa: só os empregados de serviço trabalham. As modificações faturam-se a um cliente, que aceita ou recusa a fatura, e o empregado recebe a comissão.
Toda a empresa tem um job do framework. Se o job não existir, o script cria-o no QBCore, no Qbox ou no ESX com os graus de Config.JobGrades. Quem é contratado, promovido ou fica dono recebe esse job no grau certo, e quem é despedido fica com Config.UnemployedJob.
#Menu de staff (/mecanicoadmin)
| Separador | O que tem |
|---|---|
| Geral | Nome, tipo (self-service ou empresa), logótipo, job, blip, funcionalidades e regras da empresa |
| Pontos no mapa | Lugares de trabalho, elevadores, dinamómetro, ponto de serviço, armazém e blip, todos postos onde estás, com TP para cada um |
| Empresa | Dono, saldo e armazém (slots e peso) |
No topo da lista de oficinas está o item Fornecedores: as lojas de peças, comuns a todas as oficinas (nome, posição, vendedor e artigos com preço).
O blip de cada oficina mostra se está aberta ou fechada.
Dica
Na empresa, a regra "Customs sem fatura pago pela empresa" decide o que acontece quando o mecânico modifica um carro sem faturar. Ligada, o valor sai do saldo da empresa. Desligada, o mecânico tem sempre de faturar um cliente.
#Empregados e serviço
Com o sistema próprio (Config.UseFrameworkJobs = false), os cargos são os de Config.Ranks e o dono gere tudo no tablet: contratar, promover, despedir, saldo e comissão. Pode-se trabalhar em várias oficinas. Para entrar ao serviço, usa o ponto de serviço da oficina, o tablet, ou o serviço do job do framework.
Com Config.UseFrameworkJobs = true, quem manda são o job, o menu do patrão e a conta da empresa no banco do framework.
#Trabalho no carro
#Customs
Câmara orbital (arrastar para rodar, roda do rato para aproximar), pré-visualização ao vivo e carrinho. Inclui performance, carroçaria, rodas, pintura (clássica, metalizada, pérola, mate, metal, cromada e RGB), luzes, interior, extras e buzinas, que tocam ao escolher. O preço é uma percentagem do valor do carro mais um valor fixo, multiplicado pelo nível, e é sempre recalculado no servidor.
#Reparar, serviços e kits
- Reparar no lugar de trabalho: os empregados fazem um minijogo (Espaço, clique ou E na zona certa) com animação.
- Serviços: 10 peças gastam-se com os quilómetros (óleo, filtro de ar, velas, pastilhas, pneus, embraiagem, suspensão e as peças dos elétricos) e o desgaste mexe na potência, velocidade, travagem e aderência. O condutor recebe avisos quando uma peça está gasta.
- Kits:
repairkit,advancedrepairkit(só mecânicos),cleaningkitetyrekit, usados em qualquer lado.
#Tuning, stance e nitro
- Tuning: motores (I4, V8, V12, elétrico, com som próprio), turbo, tração (AWD, RWD, FWD), caixas de 6 e 8 velocidades, pneus slick e todo-o-terreno, e travões cerâmicos. Usam o item da peça (
Config.TuningRequiresItem), e a peça antiga volta ao inventário. - Stance: afastamento, cambagem e altura, à frente e atrás, visíveis para todos os jogadores perto.
- Nitro: instalar com o kit e encher com a garrafa. Usa-se com LSHIFT e a purga com LCTRL (teclas mudam-se nas definições do FiveM). Tem chamas no escape e consumo controlado pelo servidor.
#Ferramentas
- Controlador de luzes (item): néons, modos pisca, respira e arco-íris, e xénon, dentro do carro.
- Dinamómetro: potência, binário, rotações e velocidade máxima, com o gráfico ao vivo.
- Elevador: PAGEUP sobe, PAGEDOWN desce e E termina.
#Tablet
/tablet ou o item tablet_mecanico (só empregados; o item tem de ser criado). Tem 9 aplicações:
| App | O que faz |
|---|---|
| Início | Resumo da oficina, serviço, aberta ou fechada, anúncio para a cidade |
| Veículo | Estado, quilómetros, peças e histórico do carro ligado |
| Serviço | Trocar peças gastas |
| Tuning | Instalar e tirar peças de performance |
| Stance | Instalar o kit e ajustar ao vivo |
| Faturas | Passar e cancelar faturas |
| Encomendas | Encomendar peças, que chegam ao armazém |
| Equipa | Contratar, cargos e despedir |
| Gestão | Saldo, depósitos, levantamentos e comissão |
#Lojas, encomendas e armazém
- Fornecedores: uma lista única para todas as oficinas (no primeiro arranque vem de
Config.Suppliers; depois edita-se em/mecanicoadmin→ Fornecedores). Só os mecânicos veem o vendedor e o marcador. A compra é paga pela oficina onde o mecânico está de serviço (Config.UseSocietyFund) ou por ele. - Encomendas: pedidas no tablet, chegam ao armazém ao fim de
Config.Orders.deliveryMinutese recolhem-se lá. O que não couber no inventário fica à espera. - Armazém: partilhado pelos empregados (ox_inventory, qb-inventory ou inventários antigos).
#Comandos
| Comando | Quem | O que faz |
|---|---|---|
/mecanicoadmin | Staff | Menu de staff das oficinas |
/tablet | Empregados | Abre o tablet |
/faturas | Todos | Faturas por pagar (em inglês: /invoices) |
#Opções principais
| Opção | Por defeito | Descrição |
|---|---|---|
Config.Locale | 'pt' | Idioma: pt ou en |
Config.UseFrameworkJobs | false | false = empregados próprios; true = job e conta do framework |
Config.SyncFrameworkJob | true | Dá o job do framework a quem é contratado |
Config.Commission | 10 | % das faturas pagas para o mecânico |
Config.UseSocietyFund | true | Peças e encomendas pagas pela empresa |
Config.Repair.price | 1500 | Reparação no self-service |
Config.TuningRequiresItem | true | O tuning gasta o item da peça |
Config.ShopPed | 's_m_m_lathandy_01' | Vendedor das lojas |
Config.Servicing.mileageHud | true | Barra dos km no ecrã (false esconde; o nitro instalado continua a aparecer) |
Config.Lift.height | 1.9 | Altura máxima do elevador (baixa se a MLO deixar de desenhar o carro lá em cima) |
Config.AdminCommand | 'mecanicoadmin' | Comando do menu de staff |
#Configuração completa
Config = {}
-- ------------------------------------------------------------------ geral / general
Config.Locale = 'pt' -- 'pt' | 'en'
Config.Framework = 'auto' -- 'auto' | 'qb' | 'qbx' | 'esx'
Config.UseOxNotify = false
Config.Currency = '$'
Config.CurrencyLocale = 'pt-PT' -- formato dos números na interface
Config.InteractKey = 38 -- E
Config.Debug = false
-- Empregados: false = sistema próprio (contratar/despedir/cargos/saldo no tablet, podes trabalhar em várias oficinas)
-- true = empregos do framework (job + boss menu + conta da empresa no banco do framework)
Config.UseFrameworkJobs = false
-- Cargos do sistema próprio (0 = mais baixo). manage = gere empregados, saldo e definições.
-- grade = grau do job no framework (com Config.SyncFrameworkJob)
Config.Ranks = {
[0] = { label = 'Aprendiz', manage = false, grade = 0 },
[1] = { label = 'Mecânico', manage = false, grade = 2 },
[2] = { label = 'Chefe de oficina', manage = true, grade = 3 },
[3] = { label = 'Dono', manage = true, grade = 4 },
}
-- Sistema próprio + job do framework: quem é contratado/promovido/fica dono numa oficina com `job`
-- passa a ter esse job no framework (grau acima), e o "de serviço" do tablet liga o serviço do job.
-- Despedido -> Config.UnemployedJob.
Config.SyncFrameworkJob = true
-- Cada oficina de empresa TEM de ter um job. Se o job não existir no framework (QBCore/Qbox/ESX) é criado com estes graus.
-- (os graus usados pelos cargos acima são 0, 2, 3 e 4; o 4 é o patrão)
Config.JobGrades = {
[0] = { name = 'Recruta', payment = 50 },
[1] = { name = 'Aprendiz', payment = 75 },
[2] = { name = 'Mecânico', payment = 100 },
[3] = { name = 'Chefe de oficina', payment = 125 },
[4] = { name = 'Patrão', payment = 150, isboss = true },
}
Config.UnemployedJob = 'unemployed'
-- ------------------------------------------------------------------ tablet
Config.Tablet = {
item = 'tablet_mecanico', -- usar o item abre o tablet (nil = só comando; vários: { 'tablet_mecanico', 'mechanic_tablet' })
command = 'tablet',
connectDistance = 6.0, -- distância para ligar o tablet a um veículo
}
-- ------------------------------------------------------------------ preços / pricing
-- Preço de cada mod = valor do carro × percentVehVal (+ price fixo), × (1 + priceMult × nível)
Config.PricesAsPercentOfValue = true
Config.PricesIncludeFixed = true
Config.DefaultVehicleValue = 50000 -- quando não se sabe o valor do carro
Config.UseSocietyFund = true -- compras de peças e encomendas pagas pela empresa (false = pelo empregado)
Config.Commission = 10 -- % das faturas pagas que vai para o empregado (o resto para a empresa)
Config.SelfServiceDiscount = 0 -- % de desconto nas oficinas self-service
-- ------------------------------------------------------------------ reparar
Config.Repair = {
price = 1500, -- self-service: preço da reparação completa
time = 12, -- segundos (empregados: com minijogo)
minigame = true,
}
-- Kits de reparação (itens). engine/body = até que valor recupera (0-1000)
Config.RepairKits = {
repairkit = { engine = 650, body = 650, time = 10, mechanicOnly = false },
advancedrepairkit = { engine = 1000, body = 1000, time = 15, mechanicOnly = true },
cleaningkit = { clean = true, time = 5 },
tyrekit = { tyres = true, time = 6 },
}
-- ------------------------------------------------------------------ nitro
Config.Nitrous = {
kitItem = 'nitrous_install_kit', -- instala o sistema no carro
bottleItem = 'nitrous_bottle', -- garrafa cheia (enche o sistema)
emptyItem = 'empty_nitrous_bottle',-- garrafa vazia que fica quando enches
key = 'LSHIFT', -- tecla para usar (no carro)
power = 35.0, -- aumento de potência enquanto está ligado
usePerSecond = 12, -- % da garrafa gasta por segundo
purgeKey = 'LCONTROL', -- purga (só efeito)
}
-- ------------------------------------------------------------------ outros itens
Config.Items = {
stancer = 'stancer_kit', -- instala o stance no carro
lighting = 'lighting_controller', -- controlador de luzes (usar dentro do carro)
}
-- ------------------------------------------------------------------ elevador / dyno
Config.Lift = {
height = 1.9, speed = 0.012, -- altura máxima (m). Se a MLO da oficina deixar de desenhar o carro lá em cima, baixa (ex.: 1.4)
-- props do elevador: se estes modelos existirem no servidor (ex.: o recurso grátis jg-mechanic-props, licença GPL-3.0),
-- aparece a base e a plataforma sobe com o carro (igual para todos). Sem eles, o carro sobe sozinho.
props = { base = 'jg_lift_stand', platform = 'jg_lift' },
propsDistance = 80.0,
}
Config.Dyno = { duration = 9 } -- segundos do teste no dinamómetro
-- ------------------------------------------------------------------ encomendas de peças
Config.Orders = {
deliveryMinutes = 10, -- tempo até chegarem ao armazém
items = { -- o que se pode encomendar e o preço por unidade
{ name = 'repairkit', price = 250 }, { name = 'advancedrepairkit', price = 600 },
{ name = 'cleaningkit', price = 60 }, { name = 'tyrekit', price = 180 },
{ name = 'engine_oil', price = 120 }, { name = 'air_filter', price = 90 }, { name = 'spark_plug', price = 70 },
{ name = 'clutch', price = 650 }, { name = 'brakepad_set', price = 300 }, { name = 'tyre_set', price = 700 },
{ name = 'suspension_parts', price = 900 }, { name = 'ev_battery', price = 2500 }, { name = 'ev_coolant', price = 150 },
{ name = 'ev_motor', price = 3000 }, { name = 'nitrous_install_kit', price = 4500 }, { name = 'nitrous_bottle', price = 900 },
{ name = 'stancer_kit', price = 3500 }, { name = 'lighting_controller', price = 1200 },
{ name = 'turbo_kit', price = 9000 }, { name = 'awd_drivetrain', price = 12000 }, { name = 'rwd_drivetrain', price = 9000 },
{ name = 'fwd_drivetrain', price = 7000 }, { name = 'gearbox_6', price = 6000 }, { name = 'gearbox_8', price = 9000 },
{ name = 'slick_tyres', price = 5000 }, { name = 'offroad_tyres', price = 3500 }, { name = 'ceramic_brakes', price = 7500 },
{ name = 'v8_engine', price = 25000 }, { name = 'v12_engine', price = 45000 }, { name = 'i4_engine', price = 12000 },
{ name = 'ev_engine', price = 30000 },
},
}
-- ------------------------------------------------------------------ oficinas / locations
-- type: 'self' (self-service: o próprio jogador paga e modifica) | 'owned' (empresa com empregados)
-- bays: lugares onde se trabalha no carro (customs, reparar). lifts: elevadores. dyno: dinamómetro.
-- stash/shop: armazém e loja de peças (owned). job: emprego no framework (obrigatório nas empresas; criado se não existir).
-- features: o que esta oficina faz. Os pontos editam-se no jogo com /mecanicoadmin.
Config.Locations = {
lscburton = {
label = 'Los Santos Customs Burton', type = 'self', logo = 'lsc', job = 'mechanic',
blip = { sprite = 72, color = 47, coords = vector3(-337.38, -136.92, 39.01) },
bays = { vector4(-337.38, -136.92, 38.60, 69.0) },
features = { customs = true, repair = true },
},
lscmesa = {
label = 'Los Santos Customs La Mesa', type = 'self', logo = 'lsc', job = 'lscmesa',
blip = { sprite = 72, color = 47, coords = vector3(731.80, -1088.80, 22.17) },
bays = { vector4(731.80, -1088.80, 21.80, 90.0) },
features = { customs = true, repair = true },
},
lscairport = {
label = 'Los Santos Customs Aeroporto', type = 'self', logo = 'lsc', job = 'lscairport',
blip = { sprite = 72, color = 47, coords = vector3(-1155.30, -2007.20, 13.18) },
bays = { vector4(-1155.30, -2007.20, 12.80, 315.0) },
features = { customs = true, repair = true },
},
lscharmony = {
label = 'Los Santos Customs Harmony', type = 'self', logo = 'lsc', job = 'lscharmony',
blip = { sprite = 72, color = 47, coords = vector3(1175.00, 2640.50, 37.75) },
bays = { vector4(1175.00, 2640.50, 37.40, 0.0) },
features = { customs = true, repair = true },
},
lscpaleto = {
label = "Beeker's Garage", type = 'self', logo = 'lsc', job = 'beeker',
blip = { sprite = 72, color = 47, coords = vector3(110.80, 6626.40, 31.79) },
bays = { vector4(110.80, 6626.40, 31.40, 225.0) },
features = { customs = true, repair = true },
},
bennys = {
label = "Benny's Original Motor Works", type = 'owned', logo = 'bennys', job = 'bennys',
blip = { sprite = 446, color = 5, coords = vector3(-205.70, -1310.70, 31.30) },
bays = {
vector4(-222.50, -1329.60, 30.50, 270.0), vector4(-222.50, -1322.60, 30.50, 270.0),
vector4(-200.20, -1311.20, 30.90, 180.0),
},
lifts = { vector4(-214.30, -1334.10, 30.40, 0.0) },
dyno = vector4(-197.20, -1323.40, 30.60, 90.0),
stash = vector3(-224.40, -1333.80, 30.89),
features = { customs = true, repair = true, servicing = true, tuning = true, stance = true, nitrous = true, lighting = true, dyno = true, lift = true },
stashSlots = 80, stashWeight = 2000000,
},
}
-- ------------------------------------------------------------------ fornecedores de peças
-- Uma lista única para TODAS as oficinas: qualquer mecânico compra aqui e paga a oficina onde está de serviço.
-- Só os mecânicos os veem. Isto é só a semente do primeiro arranque: depois edita-se em /mecanicoadmin → Fornecedores.
Config.Suppliers = {
{
name = 'Fornecedor de Cosméticos', coords = vector4(109.15, 6631.66, 31.78, 0.0),
items = {
{ name = 'stancer_kit', price = 3500 }, { name = 'lighting_controller', price = 1200 }, { name = 'cleaningkit', price = 60 },
},
},
{
name = 'Fornecedor de Performance', coords = vector4(1172.80, 2635.54, 37.79, 0.0),
items = {
{ name = 'repairkit', price = 300 }, { name = 'advancedrepairkit', price = 700 }, { name = 'tyrekit', price = 220 },
{ name = 'engine_oil', price = 150 }, { name = 'air_filter', price = 110 }, { name = 'spark_plug', price = 90 },
{ name = 'brakepad_set', price = 350 }, { name = 'clutch', price = 750 }, { name = 'tyre_set', price = 800 },
{ name = 'suspension_parts', price = 1000 }, { name = 'turbo_kit', price = 9000 }, { name = 'v8_engine', price = 25000 },
{ name = 'nitrous_install_kit', price = 4500 }, { name = 'nitrous_bottle', price = 900 }, { name = 'tablet_mecanico', price = 1500 },
},
},
}
-- ------------------------------------------------------------------ admin
Config.AdminCommand = 'mecanicoadmin'
-- vendedor (NPC) das lojas de peças; cada loja pode ter outro modelo ou nenhum (no /mecanicoadmin)
Config.ShopPed = 's_m_m_lathandy_01'
Config.ShopPedDistance = 60.0
Config.AdminAce = 'drs.mechanic'
-- Discord (vazio = desligado)
Config.Webhook = ''#Base de dados
-- drs_mechanic: tabelas (também são criadas sozinhas no primeiro arranque)
CREATE TABLE IF NOT EXISTS drs_mechanic_locations (
id VARCHAR(50) NOT NULL,
data LONGTEXT NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_business (
location VARCHAR(50) NOT NULL,
owner VARCHAR(60) DEFAULT NULL,
owner_name VARCHAR(100) DEFAULT NULL,
balance INT NOT NULL DEFAULT 0,
`open` TINYINT(1) NOT NULL DEFAULT 0,
commission INT NOT NULL DEFAULT 10,
PRIMARY KEY (location)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_employees (
location VARCHAR(50) NOT NULL,
citizenid VARCHAR(60) NOT NULL,
name VARCHAR(100) DEFAULT NULL,
grade INT NOT NULL DEFAULT 0,
hired_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (location,
citizenid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_vehicles (
plate VARCHAR(12) NOT NULL,
mileage DOUBLE NOT NULL DEFAULT 0,
parts LONGTEXT NULL,
tuning LONGTEXT NULL,
stance LONGTEXT NULL,
nitrous LONGTEXT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (plate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_invoices (
id INT NOT NULL AUTO_INCREMENT,
location VARCHAR(50) NOT NULL,
from_cid VARCHAR(60) NULL,
from_name VARCHAR(100) NULL,
to_cid VARCHAR(60) NULL,
to_name VARCHAR(100) NULL,
items LONGTEXT NOT NULL,
total INT NOT NULL DEFAULT 0,
status VARCHAR(12) NOT NULL DEFAULT 'pending',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
paid_at TIMESTAMP NULL,
PRIMARY KEY (id),
KEY location (location),
KEY to_cid (to_cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_orders (
id INT NOT NULL AUTO_INCREMENT,
location VARCHAR(50) NOT NULL,
by_name VARCHAR(100) NULL,
items LONGTEXT NOT NULL,
total INT NOT NULL DEFAULT 0,
status VARCHAR(12) NOT NULL DEFAULT 'pending',
deliver_at INT NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY location (location)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS drs_mechanic_history (
id INT NOT NULL AUTO_INCREMENT,
plate VARCHAR(12) NOT NULL,
location VARCHAR(50) NULL,
kind VARCHAR(20) NOT NULL,
detail VARCHAR(120) NULL,
by_name VARCHAR(100) NULL,
mileage DOUBLE NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY plate (plate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;#Para programadores
local km, unidade = exports.drs_mechanic:GetMileage(matricula)
local dados = exports.drs_mechanic:GetVehicleData(matricula) -- { mileage, parts, tuning, stance, nitrous }#Segurança
O servidor valida tudo: acesso à oficina, estar de serviço, distância ao carro e ao ponto, itens, saldo, tempo de cada trabalho e preços (o Customs recalcula o preço de cada peça). Só se guardam no carro as modificações pagas, e as faturas não se cobram duas vezes.
#Resolução de problemas
"Tens de estar de serviço" — entra ao serviço no ponto de serviço da oficina, no tablet ou no job do framework.
"A empresa não tem job" — escreve o job em /mecanicoadmin → Geral e guarda. Se não existir, é criado.
O elevador diz que o carro tem pessoas — sai toda a gente do carro, incluindo NPCs.
Não vejo o fornecedor — só os empregados de uma oficina o veem. Para comprar tens de estar de serviço (ou trabalhar numa só oficina).
As modificações desaparecem quando guardo o carro — o carro tem de ter dono (estar em player_vehicles ou owned_vehicles). Os carros sem dono só mudam enquanto existem.