DRS MDT
Tablet da polícia: fichas de cidadãos com fotografia, ocorrências com código penal, mandados aprovados pelo tribunal, viaturas com localização, mapa com todas as unidades, câmaras de segurança e chat entre agentes. Permissões por cargo e toda a lógica validada no servidor. Funciona com Qbox, QBCore e ESX.
Dica
O MDT funciona sozinho, mas ganha páginas extra com os outros scripts DRS da polícia: Police Job (BOLO, provas do laboratório, indicativos e horas de serviço), Dispatch (chamadas e estado das unidades) e Prison (pena aplicada pela ocorrência, reclusos e registo prisional). Sem eles, essas páginas simplesmente não aparecem.
#Requisitos
| Recurso | Obrigatório |
|---|---|
oxmysql | Sim |
| Qbox, QBCore ou ESX | Sim (deteção automática) |
screenshot-basic | Não — para tirar fotografias em jogo |
drs_policejob | Não — BOLO, provas, indicativos e horas de serviço |
drs_dispatch | Não — página de chamadas |
drs_prison | Não — prisão pela ocorrência e registo prisional |
#Instalação
- Coloca
drs_mdtemresources. - Adiciona ao
server.cfg, depois dooxmysqle da framework (e dos outros scripts DRS da polícia, se os tiveres):
ensure oxmysql
ensure qb-core
ensure screenshot-basic
ensure drs_policejob
ensure drs_dispatch
ensure drs_prison
ensure drs_mdt- As tabelas (
drs_mdt_*) são criadas sozinhas no primeiro arranque. As multas usam a tabeladrs_pd_fines, a mesma dodrs_policejob. - Ajusta os departamentos e as permissões em
Config.Jobse o código penal emConfig.Charges. - Opcional: para mostrar a foto do Discord de cada agente, põe o token de um bot no
server.cfg:
set drs_discord_bot_token "O_TEU_TOKEN"#Abrir o MDT
| Forma | Como |
|---|---|
| Comando | /mdt (muda em Config.Command; false desliga) |
| Tecla | Em Config.Key, ex.: 'F9'. Cada jogador pode mudá-la em Definições → Atalhos → FiveM |
| Item | Em Config.Item, ex.: 'mdt' — usar o item abre o tablet |
| Só no carro | Config.OnlyInVehicle = true só deixa abrir dentro de um veículo de emergência |
Com Config.RequireDuty = true, só abre de serviço. Os juízes (Config.Warrants.Court.Jobs) abrem o MDT em modo tribunal.
#Departamentos e permissões
Cada emprego em Config.Jobs tem o seu nome, cor e permissões. Em perms defines o cargo mínimo de cada ação (o que faltar fica a 0):
| Permissão | O que desbloqueia |
|---|---|
report_delete | Apagar ocorrências |
report_edit_all | Editar ocorrências de outros agentes |
warrant / warrant_close | Pedir mandados / marcá-los como cumpridos |
license | Ver os botões das licenças (cada licença tem ainda o seu cargo em Config.Licenses) |
fine | Multar pelo MDT |
process | Aplicar a pena de uma ocorrência (multa + prisão) |
bolo | Marcar viaturas como procuradas |
notice | Publicar avisos no painel |
profile_edit | Editar notas, foto e etiquetas das pessoas |
evidence_add / evidence_delete | Registar / apagar provas |
map / cams / chat / roster | Mapa, câmaras, chat e efetivo |
charges_edit | Editar o código penal ('boss' = só o patrão) |
#Funcionalidades
#Painel
Cartão de boas-vindas com indicativo, cargo, horas de serviço do dia e a foto do Discord. Ações rápidas (nova ocorrência, procurar pessoa, ver matrícula, pedir mandado), estatísticas (unidades de serviço, chamadas, mandados, pedidos ao tribunal, ocorrências e reclusos), mini-mapa em direto, avisos do departamento e as últimas ocorrências e mandados.
#Mapa em direto
Mapa real do GTA com os agentes de serviço e as chamadas ativas, atualizado a cada Config.Map.Refresh segundos. Clica num agente para ver o nome e o estado e marcar o GPS até ele.
#Pessoas
- Pesquisa por nome, apelido ou ID.
- Fotografia: mugshot tirado em jogo (
screenshot-basic), link, ou automático quando a polícia vê a identificação ou aplica uma pena (Config.Photo.Auto). A imagem fica na base de dados (~25 KB). - Dados pessoais, emprego, telefone e impressão digital.
- Etiquetas (
Config.Tags: perigoso, armado, gang…) e notas. - Licenças (
Config.Licenses), cada uma com o seu cargo mínimo para dar ou tirar. No QBCore/Qbox usametadata.licences; no ESX, a tabelauser_licenses. - Viaturas, propriedades (casas, apartamentos, motel), multas, multas pendentes e registo prisional.
- Multar pelo MDT. Com
Config.Fines.Offline = true, quem está offline fica com a multa pendente e paga quando entrar.
#Ocorrências
- Cria a ocorrência: título, tipo (
Config.ReportTypes), local (botão "aqui"), descrição e agentes envolvidos. - Junta os suspeitos e as acusações do código penal: a multa e os meses são somados sozinhos. Podes ajustar a pena à mão.
- Aplicar pena: multa + prisão com um clique. Com
Config.Process.RequireNearby, o suspeito tem de estar a menos deDistancemetros. - Junta imagens e vídeos (imgur, Discord, YouTube, Medal, mp4 — até
Config.MaxMedia) e as provas registadas ou do laboratório.
Depois de processado, um suspeito já não pode ser alterado.
#Mandados pelo tribunal
Com Config.Warrants.Court.Enabled = true, a polícia pede o mandado e o juiz aprova ou recusa no próprio MDT, com uma nota. Os mandados aprovados valem Config.Warrants.Days dias e quem pediu é avisado. Separadores Pendentes / Ativos / Histórico. Sem tribunal, a polícia emite os mandados diretamente. Com PoliceApproveGrade, um cargo da polícia pode aprovar quando não há juízes.
#Viaturas
Viaturas procuradas (BOLO, roubadas e donos com mandado) logo à entrada. Imagem do modelo, matrícula, dono com foto e carta de condução, estado, garagem, apreensão, quilómetros, seguro, combustível, motor e carroçaria. Localização atual no mapa se a viatura estiver na rua, fotografias tiradas em jogo (até Config.MaxVehiclePhotos) e histórico de ocorrências e multas de radar. O radar do carro de patrulha avisa de viaturas roubadas e de donos com mandado.
#Provas, chamadas, câmaras e chat
- Provas com tipo (
Config.EvidenceTypes), descrição, fotos e vídeos. - Chamadas do
drs_dispatch, com mapa, "Responder" e "Criar ocorrência". - Câmaras de segurança com imagem real do jogo (
Config.Cameras). Setas rodam, rato/scroll aproxima, ←/→ troca de câmara e Backspace sai. - Chat entre agentes.
- Código penal editável no próprio MDT (quem tiver
charges_edit). - Reclusos e efetivo com horas de serviço.
#Código penal
Cada categoria tem uma cor e uma lista de crimes com multa e meses (0 = sem prisão):
Config.Charges = {
{
category = 'Trânsito', color = '#60a5fa',
items = {
{ id = 't1', label = 'Excesso de velocidade', fine = 300, months = 0 },
{ id = 't3', label = 'Condução perigosa', fine = 1500, months = 5 },
},
},
}Os totais são sempre calculados no servidor a partir desta lista. Os id têm de ser únicos.
#Câmaras de segurança
Config.Cameras = {
{ label = 'Fleeca — Praça Legion', coords = vector3(160.0, -1055.0, 36.0), heading = 36.0, pitch = -20.0 },
}coords é a posição da câmara, heading para onde olha e pitch a inclinação (negativo = para baixo).
#Opções principais
| Opção | Por defeito | Descrição |
|---|---|---|
Config.Locale | 'pt' | Idioma: pt ou en |
Config.Command | 'mdt' | Comando para abrir |
Config.Key | '' | Tecla para abrir (vazio = sem tecla) |
Config.Item | false | Item que abre o MDT |
Config.OnlyInVehicle | false | Só dentro de um veículo de emergência |
Config.RequireDuty | true | Só de serviço |
Config.Process.MaxMonths | 300 | Pena máxima |
Config.Fines.Offline | true | Multas a jogadores offline ficam pendentes |
Config.Warrants.Days | 7 | Validade dos mandados |
Config.Warrants.Court.Enabled | true | Mandados precisam do tribunal |
Config.Map.Enabled | true | Mapa em direto |
Config.Photo.Auto | true | Mugshot automático |
Config.Webhook | '' | Webhook do Discord |
#Configuração completa
Config = {}
-- Idioma / Language: 'pt' ou 'en'
Config.Locale = 'pt'
Config.Framework = 'auto'
Config.UseOxNotify = false
Config.StaffGroups = { 'god', 'admin', 'superadmin' }
Config.Debug = false
Config.Currency = '€'
-- ------------------------------------------------------------------ abrir / open
Config.Command = 'mdt' -- false = sem comando / no command
Config.Key = '' -- ex.: 'F9' ('' = sem tecla) / e.g. 'F9' ('' = no key)
Config.Item = false -- ex.: 'mdt' — usar o item abre o MDT / using the item opens the MDT
Config.OnlyInVehicle = false -- só dentro de um veículo de emergência / only inside an emergency vehicle
Config.RequireDuty = true
Config.TabletAnim = true
-- ------------------------------------------------------------------ departamentos / departments
-- perms = cargo mínimo para cada ação (as que faltam ficam a 0)
-- perms = minimum grade for each action (anything missing is 0)
Config.Jobs = {
police = {
label = 'PSP', title = 'Polícia de Segurança Pública', color = '#3b82f6',
perms = {
report_delete = 3, -- apagar ocorrências / delete reports
report_edit_all = 2, -- editar ocorrências de outros / edit other officers' reports
warrant = 1, -- pedir mandados ao tribunal (ou emitir, sem tribunal) / request (or issue) warrants
warrant_close = 1, -- marcar como cumprido / mark served
license = 2, -- ver os botões das licenças (cada licença tem ainda o seu cargo em Config.Licenses)
-- license buttons (each license also has its own grade in Config.Licenses)
fine = 0, -- multar pelo MDT / fine from the MDT
process = 0, -- aplicar pena da ocorrência (multa + prisão) / apply report sentence
bolo = 1,
notice = 3, -- avisos no painel / dashboard notices
profile_edit = 0, -- notas, foto e etiquetas / notes, photo and tags
evidence_add = 0, -- registar provas / add evidence
evidence_delete = 3,
map = 0, -- ver o mapa com os agentes / see the live map
cams = 0, -- câmaras de segurança / security cameras
chat = 0, -- chat entre agentes / officer chat
charges_edit = 'boss', -- editar o código penal: 'boss' = só o patrão / edit the penal code: 'boss' = boss only
roster = 0,
},
},
-- sheriff = { label = 'GNR', title = 'Guarda Nacional Republicana', color = '#16a34a', perms = { notice = 4 } },
}
-- ------------------------------------------------------------------ processar / processing
Config.Process = {
RequireNearby = true, -- o suspeito tem de estar perto do agente / suspect must be near the officer
Distance = 15.0,
MaxMonths = 300,
}
-- ------------------------------------------------------------------ multas / fines
Config.Fines = {
Account = 'bank',
AllowDebt = true, -- fica com saldo negativo se não tiver dinheiro / may go negative
ToSociety = 1.0, -- parte para a conta do departamento (0-1) / share to the society
-- Offline: a multa fica pendente e é cobrada quando entrar / Offline: charged when the player joins
Offline = true,
}
-- ------------------------------------------------------------------ licenças / licenses
-- QBCore/Qbox: metadata.licences | ESX: tabela user_licenses
-- grade = cargo mínimo para dar ou tirar ESTA licença / minimum grade to grant or revoke THIS license
Config.Licenses = {
{ id = 'driver', label = 'Carta de condução', grade = 2 },
{ id = 'weapon', label = 'Licença de uso e porte de arma', grade = 4 },
{ id = 'business', label = 'Licença comercial', grade = 3 },
{ id = 'pilot', label = 'Licença de piloto', grade = 3 },
}
-- ------------------------------------------------------------------ mandados / warrants
Config.Warrants = {
Days = 7, -- validade depois de aprovado / validity once approved
-- Com o tribunal ligado a polícia só PEDE o mandado; o tribunal aprova ou recusa no próprio MDT.
-- With the court on, the police only REQUEST the warrant; the court approves or rejects it in the MDT.
Court = {
Enabled = true,
Name = 'Tribunal Judicial de Los Santos',
-- Empregos do tribunal = cargo mínimo. Abrem o MDT em modo tribunal (pessoas, ocorrências, mandados).
-- Court jobs = minimum grade. They open the MDT in court mode (people, reports, warrants).
Jobs = { judge = 0 },
Color = '#a855f7',
},
-- Cargo da polícia que também pode aprovar pedidos quando não há juízes (false = só o tribunal)
-- Police grade that may also approve requests when there are no judges (false = court only)
PoliceApproveGrade = false,
}
-- ------------------------------------------------------------------ mapa / live map
-- Mapa do GTA com os agentes de serviço e as chamadas / GTA map with on-duty officers and calls
Config.Map = {
Enabled = true,
-- Mosaicos do mapa ({style} = game | render | print) / Map tiles
TileUrl = 'https://s.rsg.sc/sc/images/games/GTAV/map/{style}/{z}/{x}/{y}.jpg',
Style = 'game',
Refresh = 3, -- segundos / seconds
}
-- ------------------------------------------------------------------ fotografias / photos
-- "Tirar foto" no perfil usa o screenshot-basic e guarda a imagem na base de dados (pequena, ~25 KB)
-- "Take photo" in the profile uses screenshot-basic and stores the image in the database (small, ~25 KB)
-- Auto = mugshot automático quando a polícia vê a identificação (se ainda não houver foto) e quando aplica uma pena
-- Auto = automatic mugshot when police check the ID (if there is no photo yet) and when a sentence is applied
Config.Photo = { Resource = 'screenshot-basic', Size = 320, Quality = 0.82, Auto = true }
-- ------------------------------------------------------------------ provas / evidence
Config.EvidenceTypes = {
{ id = 'photo', label = 'Fotografia', icon = 'fa-camera' },
{ id = 'video', label = 'Vídeo', icon = 'fa-video' },
{ id = 'document', label = 'Documento', icon = 'fa-file-lines' },
{ id = 'object', label = 'Objeto', icon = 'fa-box' },
{ id = 'statement', label = 'Depoimento', icon = 'fa-comment-dots' },
{ id = 'other', label = 'Outro', icon = 'fa-circle-question' },
}
-- Máximo de links (imagens/vídeos) por ocorrência ou prova / Max links per report or evidence
Config.MaxMedia = 12
-- Fotografias por viatura / Photos per vehicle
Config.MaxVehiclePhotos = 6
-- Imagem do modelo da viatura. Ordem: VehicleImageOverrides → imagem do stand (real_vehicleshop) → docs do FiveM (só carros base)
-- Vehicle model picture. Order: VehicleImageOverrides → car dealer picture (real_vehicleshop) → FiveM docs (base cars only)
Config.VehicleImages = 'https://docs.fivem.net/vehicles/{model}.webp'
Config.VehicleImageOverrides = {
-- ['sian'] = 'https://i.imgur.com/xxxx.png',
}
-- Foto do Discord de cada jogador (como no drs_banking): set drs_discord_bot_token "TOKEN" no server.cfg
-- Discord picture of each player (like drs_banking): set drs_discord_bot_token "TOKEN" in server.cfg
Config.DiscordTokenConvar = 'drs_discord_bot_token'
-- ------------------------------------------------------------------ câmaras / security cameras
-- coords = posição da câmara | heading = para onde olha | pitch = inclinação (negativo = para baixo)
-- Durante a câmara: setas rodam, rato/scroll aproxima, ←/→ troca de câmara, BACKSPACE sai
Config.Cameras = {
{ label = 'Loja 24/7 — Strawberry', coords = vector3(37.00, -1365.00, 36.00), heading = 31.0, pitch = -22.0 },
{ label = 'Fleeca — Praça Legion', coords = vector3(160.00, -1055.00, 36.00), heading = 36.0, pitch = -20.0 },
{ label = 'Pacific Standard — Fachada', coords = vector3(210.00, 190.00, 115.00), heading = 321.0, pitch = -18.0 },
{ label = 'Vangelico — Rua', coords = vector3(-650.00, -255.00, 45.00), heading = 312.0, pitch = -20.0 },
{ label = 'Banco de Paleto — Rua', coords = vector3(-95.00, 6445.00, 38.00), heading = 47.0, pitch = -20.0 },
{ label = 'Hospital Pillbox — Entrada', coords = vector3(280.00, -600.00, 50.00), heading = 312.0, pitch = -25.0 },
{ label = 'Aeroporto — Terminal', coords = vector3(-1060.00, -2760.00, 25.00), heading = 315.0, pitch = -15.0 },
{ label = 'Esquadra — Entrada', coords = vector3(433.00, -978.50, 33.50), heading = 90.0, pitch = -20.0 },
{ label = 'Praça Legion', coords = vector3(195.00, -915.00, 45.00), heading = 180.0, pitch = -30.0 },
}
-- ------------------------------------------------------------------ chat
Config.Chat = { MaxMessages = 150, MaxLength = 300 }
-- ------------------------------------------------------------------ etiquetas de perfil / profile tags
Config.Tags = {
{ id = 'dangerous', label = 'Perigoso', color = '#ef4444' },
{ id = 'armed', label = 'Armado', color = '#f97316' },
{ id = 'gang', label = 'Membro de gang', color = '#a855f7' },
{ id = 'probation', label = 'Liberdade condicional', color = '#eab308' },
{ id = 'informant', label = 'Informador', color = '#22c55e' },
{ id = 'mental', label = 'Instável', color = '#06b6d4' },
}
-- Tipos de ocorrência / Report types
Config.ReportTypes = {
{ id = 'incident', label = 'Ocorrência' },
{ id = 'arrest', label = 'Detenção' },
{ id = 'traffic', label = 'Trânsito' },
{ id = 'investigation', label = 'Investigação' },
{ id = 'other', label = 'Outro' },
}
-- ------------------------------------------------------------------ código penal / penal code
-- months = meses de prisão (0 = sem prisão) / months in jail (0 = no jail)
Config.Charges = {
{
category = 'Trânsito', color = '#60a5fa',
items = {
{ id = 't1', label = 'Excesso de velocidade (até 30 km/h)', fine = 300, months = 0 },
{ id = 't2', label = 'Excesso de velocidade (mais de 30 km/h)', fine = 900, months = 0 },
{ id = 't3', label = 'Condução perigosa', fine = 1500, months = 5 },
{ id = 't4', label = 'Condução sem carta', fine = 1000, months = 0 },
{ id = 't5', label = 'Condução sob o efeito de álcool', fine = 2000, months = 10 },
{ id = 't6', label = 'Fuga à polícia', fine = 3000, months = 15 },
{ id = 't7', label = 'Estacionamento ilegal', fine = 150, months = 0 },
},
},
{
category = 'Contra pessoas', color = '#f97316',
items = {
{ id = 'p1', label = 'Ofensas à integridade física', fine = 2500, months = 10 },
{ id = 'p2', label = 'Ameaças', fine = 1200, months = 5 },
{ id = 'p3', label = 'Sequestro', fine = 8000, months = 35 },
{ id = 'p4', label = 'Tentativa de homicídio', fine = 12000, months = 50 },
{ id = 'p5', label = 'Homicídio', fine = 20000, months = 90 },
{ id = 'p6', label = 'Agressão a agente da autoridade', fine = 5000, months = 25 },
},
},
{
category = 'Contra o património', color = '#eab308',
items = {
{ id = 'b1', label = 'Furto', fine = 1500, months = 5 },
{ id = 'b2', label = 'Furto de viatura', fine = 3000, months = 12 },
{ id = 'b3', label = 'Roubo a loja', fine = 6000, months = 25 },
{ id = 'b4', label = 'Roubo a banco', fine = 15000, months = 60 },
{ id = 'b5', label = 'Dano', fine = 1000, months = 0 },
{ id = 'b6', label = 'Invasão de propriedade', fine = 1500, months = 5 },
},
},
{
category = 'Armas e droga', color = '#a855f7',
items = {
{ id = 'd1', label = 'Posse de droga (consumo)', fine = 800, months = 0 },
{ id = 'd2', label = 'Tráfico de droga', fine = 8000, months = 30 },
{ id = 'd3', label = 'Posse de arma sem licença', fine = 5000, months = 15 },
{ id = 'd4', label = 'Posse de arma proibida', fine = 10000, months = 30 },
{ id = 'd5', label = 'Disparo em via pública', fine = 4000, months = 15 },
},
},
{
category = 'Ordem pública', color = '#22c55e',
items = {
{ id = 'o1', label = 'Desobediência', fine = 1500, months = 5 },
{ id = 'o2', label = 'Resistência à detenção', fine = 2500, months = 10 },
{ id = 'o3', label = 'Falsas declarações', fine = 2000, months = 5 },
{ id = 'o4', label = 'Uso de máscara em crime', fine = 1000, months = 5 },
{ id = 'o5', label = 'Evasão da prisão', fine = 10000, months = 40 },
},
},
}
-- Webhook do Discord (ocorrências, mandados, processamentos) / Discord webhook
Config.Webhook = ''#Integrações (ficheiro aberto)
O server/editable.lua não é encriptado. Tem as funções que leem e escrevem nos teus scripts: Hooks.SearchPeople, GetPerson, GetLicenses, SetLicense, PersonVehicles, SearchVehicles, VehicleDetails, PersonProperties, ChargeFine, SocietyAdd, Jail, GetBolo, SetBolo, WantedOwnerPlates, Callsign, OnDuty e JobMembers. Se usas uma garagem, casas ou prisão diferentes, adapta a função correspondente.
#Para programadores
exports.drs_mdt:AddWarrant(identifier, name, reason, author) -- cria um mandado ativo
exports.drs_mdt:HasWarrant(identifier) -- true / false
exports.drs_mdt:GetWarrants(identifier) -- mandados ativos
exports.drs_mdt:Fine(identifier, amount, reason, officer, job) -- offline fica pendente
exports.drs_mdt:GetSummary(identifier) -- { photo, warrants, reports, fines, tags }
exports.drs_mdt:Mugshot(src, force) -- tira a foto (force = substitui a atual)
exports.drs_mdt:GetFlaggedPlates() -- matrículas procuradasexports.drs_mdt:OpenProfile(identifier) -- abre o MDT na ficha da pessoaO drs_prison cria mandados sozinho (pelo AddWarrant) quando alguém foge da prisão.
#Resolução de problemas
O /mdt não abre — o teu emprego tem de estar em Config.Jobs (ou nos empregos do tribunal) e tens de estar de serviço. Com Config.OnlyInVehicle = true, entra num veículo de emergência.
Não aparece a página de chamadas / reclusos / BOLO — essas páginas dependem do drs_dispatch, drs_prison e drs_policejob. Confirma que estão a correr e que arrancam antes do drs_mdt.
O botão "Tirar foto" não faz nada — precisas do screenshot-basic a correr.
As fotos do Discord não aparecem — falta o set drs_discord_bot_token no server.cfg, ou o bot não está no teu servidor do Discord.
O mapa aparece cinzento — os mosaicos vêm de Config.Map.TileUrl. Se o endereço deixar de funcionar, troca o Style (game, render ou print) ou usa outro servidor de mosaicos.