DRS K9
Unidade cinotécnica da polícia: o agente levanta um cão no canil da esquadra, escolhe a raça e o nome, e dá-lhe ordens por um menu — seguir, sentar, deitar, entrar no carro, farejar pessoas e viaturas, e atacar. O cão tem fome e precisa de ração. A deteção é feita pelo servidor, que lê o inventário completo. 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 (nova ou antiga) | Sim (farejar e ração) |
drs_policejob | Não — dá a ração grátis no armeiro e o estado das algemas |
#Instalação
- Coloca
drs_k9emresources. - Adiciona ao
server.cfg, depois dooxmysql, da framework e do inventário:
ensure oxmysql
ensure qb-core
ensure drs_k9- Cria o item
dog_food(ver abaixo) e copia a imageminstall/images/dog_food.pngpara o teu inventário. - Em
Config.Jobsdefines os empregos e o cargo mínimo, emConfig.Kennelsos canis e emConfig.Sniff.Categorieso que o cão deteta.
#Item da ração
QBCore — dentro de qb-core/shared/items.lua:
-- drs_k9: cola dentro de qb-core/shared/items.lua (Qbox: ox_inventory/data/items.lua, ver o outro ficheiro)
-- Imagens: copia install/images/*.png para qb-inventory/html/images/
dog_food = { name = 'dog_food', label = 'Ração para cão', weight = 500, type = 'item', image = 'dog_food.png', unique = false, useable = false, shouldClose = true, combinable = nil, description = 'Ração para os cães K9 da polícia' },ox_inventory / Qbox — dentro de ox_inventory/data/items.lua:
-- drs_k9: cola dentro de ox_inventory/data/items.lua
-- Imagens: copia install/images/*.png para ox_inventory/web/images/
['dog_food'] = { label = 'Ração para cão', weight = 500, stack = true, close = true, description = 'Ração para os cães K9 da polícia', client = { image = 'dog_food.png' } },ESX — importa na base de dados:
-- drs_k9: executa na base de dados (ESX com a tabela items)
INSERT IGNORE INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('dog_food', 'Ração para cão', 1, 0, 1);Se usas o drs_policejob, a ração já está grátis no armeiro da polícia.
#Como funciona
#Canil
O cão levanta-se e entrega-se no canil da esquadra (marcador azul no estacionamento, Config.Kennels). Aí escolhes a raça (Config.Breeds: Pastor Alemão, Rottweiler, Husky, Retriever) e o nome. Só pode ter cão quem tiver o emprego e o cargo de Config.Jobs e estiver de serviço.
#Menu do cão
/k9 (ou a tecla de Config.Key) abre o menu com:
| Ordem | O que faz |
|---|---|
| Seguir | O cão segue o agente |
| Sentar / Deitar | Fica parado nessa posição |
| Parar | Cancela a ordem atual |
| Farejar pessoa | Fareja o jogador mais perto |
| Farejar veículo | Fareja a viatura mais perto (mala, porta-luvas e ocupantes) |
| Abrir porta — entrar | Põe o cão no carro |
| Dar ração | Alimenta o cão |
| Atacar | Manda o cão atacar um alvo |
#Entrar e sair do carro
- Fica junto à porta do pendura ou de uma porta de trás e escolhe "Abrir porta — entrar".
- A porta abre, o cão entra e senta-se nesse banco, e a porta fecha-se.
- Para sair, abre a porta do banco onde ele está.
A relação porta → banco está em Config.Vehicle.Doors.
#Farejar
O servidor lê o inventário todo — da pessoa, ou da mala, do porta-luvas e dos ocupantes da viatura — e compara com as categorias de Config.Sniff.Categories:
| Categoria | Exemplos |
|---|---|
drugs | joint, meth, weed_*, tudo o que tenha coke, heroin, xtc… |
chemicals | acetone, ephedrine, *_acid… |
weapons | weapon_*, *_ammo, c4, thermite |
money | markedbills, black_money, dirtymoney |
Cada categoria tem items (nomes exatos) e patterns (padrões Lua no nome: '^weed_' = começa por weed_, 'xtc' = contém xtc). A lista Ignore nunca conta (lanterna, bastão, kits de limpeza, nomes parecidos). Com ShowCategory = true, o agente vê o que o cão sentiu. Há um tempo de espera entre farejadelas (Cooldown).
Para acrescentar um item teu:
drugs = {
enabled = true,
items = { 'joint', 'meth', 'o_teu_item' },
patterns = { '^weed_', 'coke' },
},#Atacar
Escolhe Atacar no menu, aponta com o botão direito do rato para o alvo e carrega em E. O cão ataca até Config.Attack.MaxDistance metros e nunca ataca pessoas algemadas. Com OnlyPlayers = true, não ataca NPCs.
#Fome
Com Config.Hunger.Enabled, Minutes minutos depois de o levantares (ou de lhe dares ração), o cão fica com fome: não fareja nem ataca até comer dog_food ou até o trocares no canil. Recebes um aviso WarnBefore minutos antes.
#Opções principais
| Opção | Por defeito | Descrição |
|---|---|---|
Config.Locale | 'pt' | Idioma: pt ou en |
Config.Jobs | police = 1, sheriff = 1 | Empregos e cargo mínimo |
Config.RequireDuty | true | Só de serviço |
Config.Command | 'k9' | Comando do menu |
Config.Key | '' | Tecla do menu (vazio = só comando) |
Config.Hunger.Minutes | 10 | Minutos até ter fome |
Config.Sniff.Distance | 3.0 | Distância para farejar |
Config.Sniff.ShowCategory | true | Mostra o que o cão sentiu |
Config.Attack.Enabled | true | Permite atacar |
Config.Attack.MaxDistance | 40.0 | Distância máxima do ataque |
#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
-- Quem pode ter cão: emprego = cargo mínimo / Who can have a dog: job = minimum grade
Config.Jobs = { police = 1, sheriff = 1 }
Config.RequireDuty = true
-- Abrir o menu do cão / Open the dog menu
Config.Command = 'k9'
Config.Key = '' -- ex.: 'F9' ('' = só o comando) / e.g. 'F9' ('' = command only)
-- Raças (o agente escolhe no canil) / Breeds (picked at the kennel)
Config.Breeds = {
{ model = 'a_c_shepherd', label = 'Pastor Alemão' },
{ model = 'a_c_rottweiler', label = 'Rottweiler' },
{ model = 'a_c_husky', label = 'Husky' },
{ model = 'a_c_retriever', label = 'Retriever' },
}
Config.DefaultName = 'Rex'
-- ------------------------------------------------------------------ canil / kennel
-- O cão levanta-se e entrega-se aqui (estacionamento das esquadras)
-- The dog is picked up and returned here (station parking lots)
Config.Kennels = {
{ label = 'Canil — Mission Row', coords = vector3(457.20, -1017.60, 28.40) },
{ label = 'Canil — Paleto Bay', coords = vector3(-454.80, 6008.80, 31.34) },
}
Config.KennelDistance = 2.0
Config.KennelBlip = { sprite = 442, color = 3, scale = 0.6 }
Config.Marker = { type = 2, size = 0.3, color = { 59, 130, 246, 180 }, drawDistance = 12.0 }
-- ------------------------------------------------------------------ fome / hunger
-- O cão tem de comer de X em X minutos (ou ser trocado no canil). Com fome não fareja nem ataca.
-- The dog must eat every X minutes (or be swapped at the kennel). Hungry dogs don't sniff or attack.
Config.Hunger = {
Enabled = true,
Minutes = 10,
WarnBefore = 2, -- aviso X minutos antes / warning X minutes before
Item = 'dog_food', -- item para o alimentar (grátis no armeiro da polícia) / feeding item
FeedDistance = 3.0,
}
-- ------------------------------------------------------------------ viatura / vehicle
-- O agente abre a porta e o cão entra no banco dessa porta. Portas: 1 = pendura, 2 = trás esquerda, 3 = trás direita
-- The officer opens the door and the dog gets in that seat. Doors: 1 = front passenger, 2 = rear left, 3 = rear right
Config.Vehicle = {
DoorDistance = 1.8, -- distância do agente à porta / officer distance to the door
Doors = { [1] = 0, [2] = 1, [3] = 2 }, -- porta = banco / door = seat
}
-- ------------------------------------------------------------------ farejar / sniff
Config.Sniff = {
Distance = 3.0, -- distância à pessoa ou ao veículo / distance to the person or vehicle
Seconds = 6,
Cooldown = 20, -- segundos entre farejadelas / seconds between sniffs
-- Diz ao agente o que o cão sentiu (drogas, químicos...) / Tell the officer what the dog smelled
ShowCategory = true,
-- O servidor lê o inventário todo e compara com estas categorias.
-- items = nomes exatos | patterns = padrões Lua no nome (ex.: '^weed_' = começa por weed_, 'xtc' = contém xtc)
-- The server reads the whole inventory and matches these categories.
-- items = exact names | patterns = Lua patterns on the name (e.g. '^weed_' = starts with weed_, 'xtc' = contains xtc)
Categories = {
drugs = {
enabled = true,
items = { 'joint', 'oxy', 'meth', 'methbags', 'shrooms', 'coca_leaf', 'poppyresin', 'drycannabis', 'wetcannabis',
'grindedweed', 'leanblunts', 'leanbluntwrap', 'leancup', 'cupoflean', 'mdlean', 'crackrock' },
patterns = { '^weed_', 'coke', 'crack', 'heroin', 'xtc', 'lsd', 'baggy', 'meth', 'cannabis', 'cocaine', 'ecstasy', 'opium', 'codeine' },
},
chemicals = {
enabled = true,
items = { 'acetone', 'ephedrine', 'lysergic_acid', 'sulfur', 'saltpeter', 'gunpowder', 'ammonia', 'lithium',
'methylamine', 'hydrochloric_acid', 'sodium_hydroxide', 'iodine', 'red_phosphorus', 'toluene', 'pseudoephedrine' },
patterns = { 'chemical', '_acid$', 'phosphor' },
},
weapons = {
enabled = true,
items = { 'thermite', 'c4', 'explosive', 'pipe_bomb' },
patterns = { '^weapon_', '_ammo$' },
},
money = {
enabled = true,
items = { 'markedbills', 'dirtymoney', 'black_money', 'dirty_money' },
patterns = {},
},
},
-- Nunca contam (ferramentas, objetos da polícia, coisas com nomes parecidos)
-- Never count (tools, police gear, look-alike names)
Ignore = {
'gatecrack', 'weedgrinder', 'weed_nutrition', 'empty_weed_bag', 'cleaning_kit', 'cleaningkit',
'weapon_flashlight', 'weapon_nightstick', 'weapon_stungun', 'weapon_fireextinguisher', 'weapon_petrolcan',
'weapon_flare', 'weapon_ball', 'weapon_snowball', 'weapon_parachute', 'weapon_unarmed',
},
}
-- ------------------------------------------------------------------ ataque / attack
Config.Attack = {
Enabled = true,
MaxDistance = 40.0,
-- Só ataca jogadores algemados? Nunca. Só ataca quem não está algemado / Never attacks cuffed players
OnlyPlayers = false, -- true = só jogadores (não NPCs) / players only
}#Integrações (ficheiro aberto)
O server/editable.lua não é encriptado:
| Função | Para que serve |
|---|---|
Hooks.OnDuty | Saber se o agente está de serviço |
Hooks.IsCuffed | Saber se o alvo está algemado (o cão não ataca) |
Hooks.PlayerItems | Ler o inventário de uma pessoa |
Hooks.VehicleItems | Ler a mala e o porta-luvas de uma viatura |
Se usas um inventário que não seja o ox_inventory ou o qb-inventory, adapta o PlayerItems e o VehicleItems.
#Resolução de problemas
Não aparece o canil — o marcador só aparece a quem tem o emprego e cargo de Config.Jobs e está de serviço.
O cão não fareja nem ataca — está com fome. Dá-lhe dog_food pelo menu ou troca-o no canil.
O cão não encontra nada — confirma que o nome do item está em items ou bate com um pattern da categoria, e que não está na lista Ignore. Se usas outro inventário, adapta o server/editable.lua.
O cão não entra no carro — tens de estar a menos de Config.Vehicle.DoorDistance metros da porta do pendura ou de uma porta de trás.