DRS Community Service

Serviço comunitário para a polícia: formulário do agente, tarefas com animações, castigo por fuga, farda de serviço e HUD. Validado no servidor.

v1.8.3 QBCoreQboxESXStandalone drs_communityservice
Ver na loja

Serviço comunitário para a polícia. O agente escolhe o jogador, o número de tarefas e o motivo; o condenado vai para a zona, veste a farda de serviço e cumpre as tarefas uma a uma — varrer, jardinagem, apanhar lixo e limpar grafítis — com animação e objeto na mão.

#Requisitos

FrameworkQBCore, Qbox, ESX ou nenhum (deteção automática)
Base de dadosoxmysql

#Instalação

  1. Coloca a pasta drs_communityservice em resources e adiciona ao server.cfg, depois do oxmysql e do framework:
server.cfg
ensure drs_communityservice
  1. A tabela drs_community_service é criada sozinha.
  2. Ajusta os empregos, a zona, os pontos de tarefa e a farda no config.lua.
  3. Se tens outro serviço comunitário (ex.: qb-communityservice), desliga-o.

#Como funciona

  1. Um polícia em serviço (ou staff) usa /servicocomunitario perto do jogador — abre o formulário com a lista dos jogadores perto (distância calculada no servidor).
  2. Escolhe as tarefas (entre Config.MinTasks e Config.MaxTasks) e o motivo.
  3. O jogador é levado para Config.Zone.start, veste a farda e vê um HUD com as tarefas que faltam.
  4. Em cada ponto carrega em E: animação, objeto na mão e barra de progresso. Afastar-se cancela.
  5. Ao acabar é levado para Config.Zone.release e a roupa original volta.

Atenção

Sair do raio da zona conta como fuga: o jogador volta para dentro e leva Config.EscapePenalty tarefas extra. Sair do servidor não livra ninguém — o que falta fica guardado.

#Comandos

ComandoQuemO que faz
/servicocomunitariopolícia / staffAbre o formulário
/servicocomunitario [id] [tarefas] [motivo]polícia / staff / consolaAplica sem formulário
/libertarservico [id]polícia / staff / consolaLiberta o jogador
/servicotodosMostra quantas tarefas faltam

O staff é reconhecido pelos grupos em Config.StaffGroups ou pela ACE drs.communityservice.

#Tipos de tarefa

Cada tipo tem tempo, animação (ou scenario), objeto e cor do marcador. Acrescentar um tipo é só uma entrada nova:

config.lua
sweep = {
    label = 'Varrer o chão', time = 8,
    anim = { dict = 'amb@world_human_janitor@male@base', clip = 'base' },
    prop = { model = 'prop_tool_broom', bone = 28422, pos = vector3(-0.01, 0.04, -0.03), rot = vector3(0.0, 0.0, 0.0) },
    marker = { r = 96, g = 165, b = 250 },
},

E os pontos, dentro da zona: { type = 'sweep', coords = vector3(...) }.

#Opções principais

OpçãoPor defeitoDescrição
Config.Jobspolice, sheriffEmpregos que aplicam
Config.RequireDutytrueTem de estar em serviço
Config.MaxDistance10.0Distância máxima entre o agente e o jogador
Config.MinTasks / Config.MaxTasks5 / 150Limites por sentença
Config.ZoneLegion SquareCentro, raio, entrada e saída
Config.EscapePenalty5Tarefas extra por fuga
Config.DisarmDuringServicetrueSem armas nem veículos
Config.Outfithomem/mulherFarda de serviço (vazio = não muda)

#Configuração completa

config.lua
Config = {}

-- Idioma / Language: 'pt' ou 'en'
Config.Locale = 'pt'

-- Framework: 'auto' deteta Qbox/QBCore/ESX (ou 'qbx' | 'qb' | 'esx' | 'none')
Config.Framework = 'auto'

-- ------------------------------------------------------------------ quem aplica / who can sentence
-- Empregos que podem mandar para serviço comunitário / Jobs that can sentence
Config.Jobs = { 'police', 'sheriff' }
-- Cargo mínimo (0 = qualquer) e se é preciso estar em serviço / Minimum grade (0 = any) and on-duty requirement
Config.MinGrade = 0
Config.RequireDuty = true
-- O staff (ACE drs.communityservice ou grupo admin) também pode / Staff can too
Config.StaffCanSentence = true
Config.StaffGroups = { 'god', 'admin', 'superadmin' }

-- Distância máxima entre o agente e o jogador (0 = sem limite) / Max distance officer → player (0 = no limit)
Config.MaxDistance = 10.0

-- Comandos / Commands
Config.Command = 'servicocomunitario'     -- abre o formulário (ou: /servicocomunitario [id] [tarefas] [motivo])
Config.ReleaseCommand = 'libertarservico' -- /libertarservico [id]
Config.CheckCommand = 'servico'           -- o jogador vê quantas tarefas faltam / player checks remaining tasks

-- Limites de tarefas por sentença / Task limits per sentence
Config.MinTasks = 5
Config.MaxTasks = 150

-- ------------------------------------------------------------------ zona / zone
Config.Zone = {
    center = vector3(185.0, -1003.0, 29.3),
    radius = 45.0,                                -- sair daqui conta como fuga / leaving counts as escaping
    start = vector4(170.4, -994.9, 30.1, 160.0),  -- onde o jogador aparece / where the player appears
    release = vector4(133.1, -990.0, 29.5, 250.0),-- onde é solto no fim / where they are released
    blip = { sprite = 566, color = 5, scale = 0.8 },
}

-- Tarefas extra por cada fuga / Extra tasks for each escape
Config.EscapePenalty = 5
-- Tirar as armas durante o serviço (voltam no fim) / Hold weapons during service (given back at the end)
-- Só desarma na mão; o inventário não é tocado / Only unequips; the inventory is not touched
Config.DisarmDuringService = true

-- ------------------------------------------------------------------ tipos de tarefa / task types
-- time: segundos que a tarefa demora (o servidor valida) / seconds the task takes (server-checked)
-- anim: animação (dict/clip) ou scenario; prop: objeto na mão
Config.TaskTypes = {
    sweep = {
        label = 'Varrer o chão', time = 8,
        anim = { dict = 'amb@world_human_janitor@male@base', clip = 'base' },
        prop = { model = 'prop_tool_broom', bone = 28422, pos = vector3(-0.01, 0.04, -0.03), rot = vector3(0.0, 0.0, 0.0) },
        marker = { r = 96, g = 165, b = 250 },
    },
    garden = {
        label = 'Tratar do jardim', time = 10,
        scenario = 'WORLD_HUMAN_GARDENER_PLANT',
        marker = { r = 74, g = 222, b = 128 },
    },
    trash = {
        label = 'Apanhar lixo', time = 6,
        anim = { dict = 'anim@amb@drug_field_workers@rake@male_a@base', clip = 'base' },
        prop = { model = 'prop_cs_rub_binbag_01', bone = 57005, pos = vector3(0.12, 0.0, -0.05), rot = vector3(10.0, 0.0, 0.0) },
        marker = { r = 251, g = 191, b = 36 },
    },
    graffiti = {
        label = 'Limpar grafíti', time = 9,
        scenario = 'WORLD_HUMAN_MAID_CLEAN',
        marker = { r = 192, g = 132, b = 252 },
    },
}

-- Pontos de tarefa (dentro da zona) / Task spots (inside the zone)
Config.Spots = {
    { type = 'sweep',    coords = vector3(170.0, -1006.0, 29.34) },
    { type = 'sweep',    coords = vector3(177.0, -1007.9, 29.33) },
    { type = 'sweep',    coords = vector3(181.6, -1009.5, 29.34) },
    { type = 'sweep',    coords = vector3(189.3, -1009.5, 29.34) },
    { type = 'sweep',    coords = vector3(195.3, -1016.0, 29.34) },
    { type = 'trash',    coords = vector3(169.9, -1001.3, 29.34) },
    { type = 'trash',    coords = vector3(164.7, -1008.0, 29.43) },
    { type = 'trash',    coords = vector3(163.3, -1000.6, 29.35) },
    { type = 'garden',   coords = vector3(181.4, -1000.1, 29.29) },
    { type = 'garden',   coords = vector3(188.4, -1000.4, 29.29) },
    { type = 'garden',   coords = vector3(194.8, -1002.0, 29.29) },
    { type = 'garden',   coords = vector3(199.0, -1006.9, 29.29) },
    { type = 'graffiti', coords = vector3(201.5, -1004.4, 29.29) },
}

-- ------------------------------------------------------------------ roupa / clothing
-- Roupa durante o serviço (freemode). Vazio = não muda. A roupa original volta no fim.
-- Clothing during service (freemode). Empty = unchanged. The original clothes come back at the end.
-- [componente] = { drawable, texture }
Config.Outfit = {
    male = {
        [3] = { 0, 0 }, [4] = { 36, 0 }, [6] = { 25, 0 }, [8] = { 59, 0 }, [11] = { 56, 0 },
    },
    female = {
        [3] = { 14, 0 }, [4] = { 35, 0 }, [6] = { 26, 0 }, [8] = { 36, 0 }, [11] = { 49, 0 },
    },
}

-- ------------------------------------------------------------------ interface / UI
Config.InteractKey = 38            -- E
Config.InteractKeyLabel = 'E'
Config.HudPosition = 'right-center' -- 'right-center' | 'left-center' | 'top-center'

-- Webhook do Discord (vazio = desligado) / Discord webhook (empty = off)
Config.Webhook = ''

-- Notificações com ox_lib quando estiver a correr / Use ox_lib notifications when it is running
Config.UseOxNotify = false

#Para programadores

server
exports.drs_communityservice:Sentence(target, 10, 'Condução perigosa', officerSrc)  -- officer 0 = sem verificação
exports.drs_communityservice:Release(target)
exports.drs_communityservice:IsServing(src)
exports.drs_communityservice:GetRemaining(src)

O statebag communityService (true/false) está no jogador — Player(src).state.communityService.

#Resolução de problemas

"Não tens permissão para isto." — o agente não tem o emprego de Config.Jobs, não está em serviço ou tem cargo abaixo de Config.MinGrade.

"O jogador está demasiado longe." — aproxima-te (limite em Config.MaxDistance; 0 desliga).

A tarefa não conta — o jogador afastou-se do ponto ou a tarefa não durou o tempo todo; o servidor recusa.