DRS Dispatch
Central de despacho para a polícia, o INEM e os bombeiros: alertas no ecrã com todos os detalhes, blips no mapa, painel de chamadas com o estado das unidades, chamadas de cidadãos pelo 112 e deteção automática de crimes. Usa os mesmos exports do ps-dispatch, por isso os teus scripts de assaltos, droga e mortes continuam a funcionar sem mudar nada. Funciona com Qbox, QBCore e ESX.
#Requisitos
| Recurso | Obrigatório |
|---|---|
oxmysql | Sim |
| Qbox, QBCore ou ESX | Sim (deteção automática) |
drs_mdt | Não — mostra as chamadas dentro do MDT |
#Instalação
- Desliga o
ps-dispatch(ou outro dispatch). Odrs_dispatchtemprovide 'ps-dispatch': os scripts que chamamexports['ps-dispatch']:...passam a falar com ele. - Coloca
drs_dispatchemresources. - Adiciona ao
server.cfg, depois dooxmysqle da framework, e antes dos scripts que enviam alertas:
ensure oxmysql
ensure qb-core
ensure drs_dispatch
# depois: assaltos, droga, EMS, etc.- Ajusta os grupos (
Config.Groups), os comandos do 112 e as zonas sem alertas noconfig.lua.
#Teclas e comandos
| Tecla / comando | O que faz |
|---|---|
| G | Responde ao alerta no ecrã: marca o GPS e entra na chamada |
| ← / → | Vê o alerta anterior / seguinte |
| J | Abre o painel de despacho (chamadas, unidades, zonas) |
/112 mensagem | Cidadão liga para a polícia |
/112a mensagem | Chamada anónima para a polícia |
/inem mensagem | Cidadão liga para o INEM |
Cada jogador pode mudar as teclas em Definições → Atalhos → FiveM. Os comandos de chamada estão em Config.Commands.
#Quem recebe os alertas
Os alertas vão para grupos de empregos. Cada alerta diz os grupos que recebem (jobs = { 'leo' }); também podes pôr o nome de um emprego diretamente.
Config.Groups = {
leo = { 'police', 'sheriff', 'bcso', 'sasp' },
ems = { 'ambulance', 'ems' },
fire = { 'fire' },
}
Config.RequireDuty = true -- só recebe quem está de serviço#Funcionalidades
#Alertas no ecrã
- Código (ex.:
10-90), título, rua, sexo, viatura, matrícula, cor, direção e arma, conforme o alerta. - Cor por prioridade:
1urgente (vermelho, a piscar),2normal,3baixa. - Barra de tempo (
Config.Hud.Seconds), som e atéConfig.Hud.Maxalertas visíveis ao mesmo tempo.
#Mapa
- Blip e círculo de raio por alerta, a piscar nos urgentes. Tempo no mapa em
Config.BlipMinutesou emlengthde cada alerta. - Zonas: os agentes (cargo
Config.Zones.MinGradeou superior) marcam perímetros no mapa com cor e raio, visíveis para todas as unidades. Desaparecem ao fim deConfig.Zones.Minutes.
#Painel de despacho (J)
- Lista de chamadas com filtros: todas, urgentes e as minhas.
- Unidades em cada chamada.
- Estado de cada agente: disponível, patrulha, ocupado ou pausa (
Config.Statuses). - Responder ao cidadão que ligou.
- Guarda até
Config.MaxCallschamadas; cada uma sai do painel ao fim deConfig.CallMinutes.
#Chamadas de cidadãos
/112, /112a (anónimo) e /inem, com o nome e o telefone de quem ligou (ou anónimo). Opcionalmente, é preciso ter um telemóvel (Config.CallItem = 'phone'). Há um tempo de espera entre chamadas (Config.CallCooldown) e as chamadas podem ir para um webhook do Discord.
#Deteção automática
Em Config.Detect ligas ou desligas: disparos (a pé e de viatura), lutas, carjacking, tentativa de furto de viatura e explosões.
- Os polícias de serviço não geram alertas (
IgnoreOfficers). - Com
RequireWitness = true, tiros e lutas só dão alerta se um NPC tiver visto. - Armas que não contam em
Config.WeaponWhitelist(taser, extintor…). - Zonas sem alertas (
Config.NoDispatchZones, ex.: carreiras de tiro) e zonas de caça (Config.HuntingZones), que dão "caça" em vez de "tiros".
#Alertas prontos
Mais de 30 alertas em Config.Alerts. Cada nome é também um export no cliente, igual ao do ps-dispatch:
| Tipo | Alertas |
|---|---|
| Crime na rua | Shooting, VehicleShooting, Fight, CarJacking, VehicleTheft, SpeedingVehicle, SuspiciousActivity, DrugSale, Explosion, Hunting |
| Assaltos | StoreRobbery, HouseRobbery, FleecaBankRobbery, PaletoBankRobbery, PacificBankRobbery, VangelicoRobbery, ArtGalleryRobbery, HumaneRobbery, TrainRobbery, VanRobbery, UndergroundRobbery, DrugBoatRobbery, UnionRobbery, YachtHeist, BobcatSecurityHeist, SignRobbery, CarBoosting, PrisonBreak |
| Emergência | InjuriedPerson, DeceasedPerson, OfficerDown, OfficerBackup, OfficerInDistress, EmsDown |
Cada alerta tem estes campos:
StoreRobbery = {
code = '10-90', -- código mostrado
icon = 'fas fa-store', -- ícone Font Awesome
priority = 2, -- 1 urgente | 2 normal | 3 baixa
sprite = 52, color = 60, -- blip
radius = 0.0, -- círculo à volta (0 = nenhum)
length = 3, -- minutos no mapa
jobs = { 'leo' }, -- quem recebe
gender = true, -- junta o sexo do suspeito
vehicle = false, -- junta a viatura
weapon = false, -- junta a arma
},Para criar um alerta novo, basta acrescentar uma entrada: passa logo a existir exports.drs_dispatch:NomeDoAlerta() no cliente.
#Opções principais
| Opção | Por defeito | Descrição |
|---|---|---|
Config.Locale | 'pt' | Idioma: pt ou en |
Config.RequireDuty | true | Só recebe quem está de serviço |
Config.MaxCalls | 60 | Chamadas guardadas no painel |
Config.CallMinutes | 45 | Minutos até a chamada sair do painel |
Config.BlipMinutes | 3 | Minutos do blip no mapa |
Config.Keys | G / J / ← / → | Teclas por defeito |
Config.Hud.Seconds | 9 | Segundos do alerta no ecrã |
Config.CallItem | false | Item preciso para ligar para o 112 |
Config.Detect.RequireWitness | false | Tiros e lutas precisam de testemunha |
Config.Zones.Enabled | true | Perímetros no mapa |
Config.Webhook | '' | Webhook do Discord para as chamadas |
#Configuração completa
Config = {}
-- Idioma / Language: 'pt' ou 'en'
Config.Locale = 'pt'
-- Framework: 'auto' deteta Qbox/QBCore/ESX (ou 'qbx' | 'qb' | 'esx')
Config.Framework = 'auto'
Config.UseOxNotify = false
Config.StaffGroups = { 'god', 'admin', 'superadmin' }
Config.Debug = false
-- ------------------------------------------------------------------ quem recebe / who receives
-- Grupos usados nos alertas (jobs = { 'leo' }). Também se pode pôr o nome de um emprego diretamente.
-- Groups used by alerts (jobs = { 'leo' }). A job name can also be used directly.
Config.Groups = {
leo = { 'police', 'sheriff', 'bcso', 'sasp' },
ems = { 'ambulance', 'ems' },
fire = { 'fire' },
}
-- Só recebe quem está de serviço / Only on-duty players receive alerts
Config.RequireDuty = true
-- ------------------------------------------------------------------ chamadas / calls
Config.MaxCalls = 60 -- chamadas guardadas no painel / calls kept in the panel
Config.CallMinutes = 45 -- depois disto a chamada sai do painel / calls leave the panel after this
Config.BlipMinutes = 3 -- tempo do blip no mapa (cada alerta pode mudar) / map blip time (per alert override: length)
-- ------------------------------------------------------------------ teclas / keys (o jogador muda nas definições do GTA)
Config.Keys = {
Respond = 'G', -- marcar GPS e responder ao último alerta / waypoint + respond to the last alert
Panel = 'J', -- abrir o painel de despacho / open the dispatch panel
Prev = 'LEFT', -- alerta anterior no ecrã / previous alert on screen
Next = 'RIGHT', -- alerta seguinte no ecrã / next alert on screen
}
-- ------------------------------------------------------------------ ecrã / screen
Config.Hud = {
Seconds = 9, -- quanto tempo o alerta fica no ecrã / how long an alert stays on screen
Max = 3, -- alertas visíveis ao mesmo tempo / alerts visible at once
Sound = true,
}
-- ------------------------------------------------------------------ chamadas de cidadãos / citizen calls
-- /112 mensagem -> polícia; /112a mensagem -> anónimo; /inem mensagem -> EMS
Config.Commands = {
{ name = '112', jobs = { 'leo' }, anonymous = false },
{ name = '112a', jobs = { 'leo' }, anonymous = true },
{ name = 'inem', jobs = { 'ems' }, anonymous = false },
}
Config.CallCooldown = 30 -- segundos entre chamadas do mesmo jogador / seconds between calls of the same player
-- Item preciso para ligar (false = nenhum). Ex.: 'phone' / Item needed to call (false = none)
Config.CallItem = false
-- ------------------------------------------------------------------ deteção automática / automatic detection
Config.Detect = {
Shooting = true, -- tiros (a pé ou num veículo) / gunshots
Fight = true, -- lutas / melee fights
CarJacking = true, -- tirar alguém do carro / pulling someone out of a car
VehicleTheft = true, -- tentar abrir um carro trancado / trying to open a locked car
Explosion = true, -- explosões (lado do servidor) / explosions (server side)
Cooldown = 25, -- segundos entre alertas do mesmo tipo / seconds between alerts of the same type
-- Os polícias de serviço não geram alertas / On-duty police don't trigger alerts
IgnoreOfficers = true,
-- Precisa de uma testemunha (NPC que viu) para tiros e lutas / Needs an NPC witness for shots and fights
RequireWitness = false,
}
-- Armas que não geram alertas de tiros / Weapons that don't trigger gunshot alerts
Config.WeaponWhitelist = {
'WEAPON_STUNGUN', 'WEAPON_SNOWBALL', 'WEAPON_BALL', 'WEAPON_FLARE', 'WEAPON_FIREEXTINGUISHER', 'WEAPON_PETROLCAN',
}
-- Zonas sem alertas de tiros (carreiras de tiro, etc.) / No gunshot alerts here (shooting ranges, etc.)
Config.NoDispatchZones = {
{ coords = vector3(13.53, -1097.92, 29.83), radius = 25.0 }, -- Ammu-Nation (centro)
{ coords = vector3(821.36, -2163.58, 29.62), radius = 25.0 }, -- Ammu-Nation (Cypress Flats)
}
-- Zonas de caça (dá o alerta "caça" em vez de "tiros") / Hunting zones (sends "hunting" instead of "shots fired")
Config.HuntingZones = {
{ coords = vector3(-1339.0, 4618.0, 150.0), radius = 900.0 },
}
-- ------------------------------------------------------------------ zonas no mapa / map zones
-- Os agentes podem marcar perímetros no mapa para todas as unidades / Officers can mark perimeters for all units
Config.Zones = {
Enabled = true,
MinGrade = 1, -- cargo mínimo / minimum grade
Minutes = 30, -- a zona desaparece sozinha / the zone expires
MaxRadius = 400.0,
Colors = { red = 1, blue = 3, green = 2, yellow = 5, orange = 47, purple = 27 },
}
-- Estados que o agente pode escolher / Unit statuses
Config.Statuses = {
{ id = 'available', color = '#4ade80' },
{ id = 'patrol', color = '#60a5fa' },
{ id = 'busy', color = '#fbbf24' },
{ id = 'break', color = '#a1a1aa' },
}
-- ------------------------------------------------------------------ alertas / alerts
-- Nome = export no cliente (compatível com o ps-dispatch: exports['ps-dispatch']:Shooting()).
-- Name = client export (compatible with ps-dispatch: exports['ps-dispatch']:Shooting()).
-- priority: 1 = urgente (vermelho, pisca) | 2 = normal | 3 = baixa
-- sprite/color/scale: blip | radius: círculo à volta (0 = nenhum) | length: minutos no mapa
-- vehicle/gender/weapon: junta esses detalhes / adds those details
Config.Alerts = {
Shooting = { code = '10-11', icon = 'fas fa-gun', priority = 2, sprite = 110, color = 1, jobs = { 'leo' }, gender = true, weapon = true },
VehicleShooting = { code = '10-60', icon = 'fas fa-gun', priority = 2, sprite = 229, color = 1, jobs = { 'leo' }, vehicle = true, weapon = true },
Hunting = { code = '10-13', icon = 'fas fa-crosshairs', priority = 3, sprite = 141, color = 2, jobs = { 'leo' } },
Fight = { code = '10-10', icon = 'fas fa-hand-fist', priority = 3, sprite = 685, color = 69, jobs = { 'leo' }, gender = true },
CarJacking = { code = '10-35', icon = 'fas fa-car', priority = 2, sprite = 595, color = 60, jobs = { 'leo' }, vehicle = true, gender = true },
VehicleTheft = { code = '10-35', icon = 'fas fa-car-burst', priority = 3, sprite = 595, color = 60, jobs = { 'leo' }, vehicle = true },
SpeedingVehicle = { code = '10-11', icon = 'fas fa-gauge-high', priority = 3, sprite = 326, color = 84, jobs = { 'leo' }, vehicle = true },
Explosion = { code = '10-80', icon = 'fas fa-fire', priority = 1, sprite = 436, color = 1, jobs = { 'leo', 'ems' }, radius = 60.0 },
SuspiciousActivity = { code = '10-66', icon = 'fas fa-eye', priority = 3, sprite = 66, color = 37, jobs = { 'leo' }, gender = true },
DrugSale = { code = '10-13', icon = 'fas fa-cannabis', priority = 3, sprite = 501, color = 25, jobs = { 'leo' }, gender = true },
PrisonBreak = { code = '10-90', icon = 'fas fa-person-running', priority = 1, sprite = 189, color = 59, jobs = { 'leo' }, radius = 120.0 },
StoreRobbery = { code = '10-90', icon = 'fas fa-store', priority = 2, sprite = 52, color = 60, jobs = { 'leo' }, gender = true },
HouseRobbery = { code = '10-90', icon = 'fas fa-house', priority = 2, sprite = 40, color = 60, jobs = { 'leo' }, gender = true },
FleecaBankRobbery = { code = '10-90', icon = 'fas fa-vault', priority = 1, sprite = 500, color = 60, jobs = { 'leo' }, radius = 60.0 },
PaletoBankRobbery = { code = '10-90', icon = 'fas fa-vault', priority = 1, sprite = 500, color = 60, jobs = { 'leo' }, radius = 60.0 },
PacificBankRobbery = { code = '10-90', icon = 'fas fa-vault', priority = 1, sprite = 500, color = 60, jobs = { 'leo' }, radius = 80.0 },
VangelicoRobbery = { code = '10-90', icon = 'fas fa-gem', priority = 1, sprite = 617, color = 60, jobs = { 'leo' }, radius = 60.0 },
ArtGalleryRobbery = { code = '10-90', icon = 'fas fa-palette', priority = 1, sprite = 269, color = 60, jobs = { 'leo' }, radius = 60.0 },
HumaneRobbery = { code = '10-90', icon = 'fas fa-flask', priority = 1, sprite = 499, color = 60, jobs = { 'leo' }, radius = 80.0 },
TrainRobbery = { code = '10-90', icon = 'fas fa-train', priority = 1, sprite = 667, color = 60, jobs = { 'leo' }, radius = 80.0 },
VanRobbery = { code = '10-90', icon = 'fas fa-van-shuttle', priority = 1, sprite = 67, color = 60, jobs = { 'leo' }, radius = 60.0 },
UndergroundRobbery = { code = '10-90', icon = 'fas fa-dungeon', priority = 1, sprite = 486, color = 60, jobs = { 'leo' }, radius = 60.0 },
DrugBoatRobbery = { code = '10-90', icon = 'fas fa-ship', priority = 1, sprite = 427, color = 60, jobs = { 'leo' }, radius = 80.0 },
UnionRobbery = { code = '10-90', icon = 'fas fa-building-columns', priority = 1, sprite = 500, color = 60, jobs = { 'leo' }, radius = 80.0 },
YachtHeist = { code = '10-90', icon = 'fas fa-anchor', priority = 1, sprite = 455, color = 60, jobs = { 'leo' }, radius = 80.0 },
BobcatSecurityHeist = { code = '10-90', icon = 'fas fa-shield-halved', priority = 1, sprite = 487, color = 60, jobs = { 'leo' }, radius = 80.0 },
SignRobbery = { code = '10-62', icon = 'fas fa-sign-hanging', priority = 3, sprite = 358, color = 60, jobs = { 'leo' }, gender = true },
CarBoosting = { code = '10-35', icon = 'fas fa-car', priority = 2, sprite = 595, color = 60, jobs = { 'leo' }, vehicle = true },
InjuriedPerson = { code = '10-69', icon = 'fas fa-user-injured', priority = 2, sprite = 153, color = 1, jobs = { 'ems' }, gender = true },
DeceasedPerson = { code = '10-69', icon = 'fas fa-skull', priority = 2, sprite = 310, color = 1, jobs = { 'ems', 'leo' }, gender = true },
OfficerDown = { code = '10-99', icon = 'fas fa-skull', priority = 1, sprite = 526, color = 1, jobs = { 'leo', 'ems' }, officer = true },
OfficerBackup = { code = '10-32', icon = 'fas fa-people-group', priority = 1, sprite = 526, color = 3, jobs = { 'leo' }, officer = true },
OfficerInDistress = { code = '10-13', icon = 'fas fa-triangle-exclamation', priority = 1, sprite = 526, color = 1, jobs = { 'leo' }, officer = true },
EmsDown = { code = '10-99', icon = 'fas fa-truck-medical', priority = 1, sprite = 526, color = 3, jobs = { 'leo', 'ems' }, officer = true },
Call = { code = '112', icon = 'fas fa-phone', priority = 2, sprite = 480, color = 3, jobs = { 'leo' } },
}
-- Webhook do Discord para registar as chamadas do 112 / Discord webhook for 112 calls
Config.Webhook = ''#Integrações (ficheiro aberto)
O server/editable.lua não é encriptado:
| Função | Para que serve |
|---|---|
Hooks.OnDuty | Saber se alguém está de serviço |
Hooks.Callsign | Indicativo do agente (vem do drs_policejob se existir) |
Hooks.Phone | Número de telefone de quem liga para o 112 |
Hooks.OnAlert | Corre a cada alerta enviado (ex.: mandar para outro sistema) |
#Para programadores
Cliente — os mesmos do ps-dispatch (funcionam com exports['ps-dispatch'] ou exports.drs_dispatch):
exports['ps-dispatch']:StoreRobbery()
exports['ps-dispatch']:Shooting()
exports['ps-dispatch']:OfficerDown()
exports['ps-dispatch']:CustomAlert({
message = 'Alarme ativado',
dispatchCode = '10-90',
code = '10-90',
icon = 'fas fa-bell',
priority = 1,
coords = GetEntityCoords(PlayerPedId()),
sprite = 161, color = 1, scale = 1.2, length = 3,
jobs = { 'leo' },
})Servidor:
exports.drs_dispatch:SendAlert({ coords = coords, message = 'Alarme ativado', code = '10-90', icon = 'fas fa-bell', priority = 1, jobs = { 'leo' }, sprite = 161, color = 1 })
exports.drs_dispatch:SendPreset('StoreRobbery', coords)
exports.drs_dispatch:GetDispatchCalls() -- lista de chamadas ativas
-- compatibilidade com o ps-dispatch
TriggerEvent('ps-dispatch:server:notify', data)#Segurança
Os alertas pré-definidos usam a posição do jogador lida no servidor. Os alertas livres enviados por um cliente só são aceites perto do próprio jogador, todos os textos são limpos e limitados, e há limites de frequência por jogador. Um cliente modificado não consegue inventar alertas noutro sítio do mapa.
#Resolução de problemas
Não recebo alertas — o teu emprego tem de estar num grupo de Config.Groups e tens de estar de serviço (Config.RequireDuty). Os alertas de tiros não aparecem se fores tu a disparar de serviço (IgnoreOfficers).
Os scripts de assaltos não dão alerta — confirma que o ps-dispatch está desligado e que o drs_dispatch arranca antes desses scripts no server.cfg.
Alertas de tiros na carreira de tiro — acrescenta a zona em Config.NoDispatchZones.
O /112 não faz nada — há um tempo de espera entre chamadas (Config.CallCooldown) e, se Config.CallItem estiver definido, precisas desse item no inventário.