Scripts de roubo de loja e banco em FiveM: configuração e design lado do servidor

Como configurar e projetar roubos de loja e banco em FiveM: contagem de polícia, cooldowns lado do servidor, recompensas dadas apenas pelo servidor, alertas de polícia e verificações de distância.

O sintoma: jogadores roubam uma loja sem polícia online, a mesma loja é roubada dez vezes seguidas, ou um cheater dispara um evento e pega todo o payout.

Um script de roubo é uma pequena máquina de estado lado do servidor: verifique as regras, comece, aguarde, pague. A maioria dos exploits vem de colocar essas etapas no cliente. Este artigo cobre um design seguro e os erros de config que causam os problemas acima.

O fluxo que você quer

Pense em cada roubo como quatro etapas, e execute as etapas 1, 2 e 4 no servidor:

  1. Pedido de início: o cliente pede para roubar uma loja. O servidor verifica contagem de polícia, cooldown, distância e que ninguém já está roubando.
  2. Travar: o servidor marca a loja como sendo roubada e define o cooldown.
  3. Ação: o cliente toca a barra de progresso, o hack ou o lockpick.
  4. Terminar: o cliente relata feito, o servidor verifica o tempo que passou e a distância novamente, depois paga.

O cliente apenas lida com os visuais. Nunca decide o resultado.

Contagem de polícia

Exija um número mínimo de oficiais em duty, contados no servidor. Um script que lê a contagem do cliente, ou de um valor que o cliente envia, é trivial de contornar. O código de contagem está em setting up a police job. Verifique quando o roubo começar, e decida se deve ser verificado novamente antes do payout.

Cooldowns armazenados no servidor

Mantenha o estado em uma tabela do servidor, codificada por id de localização:

lua
-- server
-- [id] = { busy = bool, last = os.time(), robber = source, started = os.time() }
local robberies = {}

local function canRob(id, cooldown)
    local state = robberies[id]
    if not state then return true end
    if state.busy then return false end
    return (os.time() - state.last) >= cooldown
end

Dois detalhes importam:

  • Uma tabela na memória reseta quando o recurso reinicia. Se você quer que o cooldown sobreviva a um reinício, armazene o tempo do último roubo no banco de dados.
  • Defina busy quando o roubo começa e limpe quando termina ou quando o ladrão se desconecta, ou a loja fica trancada para sempre.

Recompensas apenas do servidor

O exploit mais comum é um evento de recompensa que o cliente pode disparar sozinho:

lua
-- WRONG: any client can fire this
RegisterNetEvent('robbery:reward', function(amount)
    exports.ox_inventory:AddItem(source, 'money', amount)
end)

A solução é não ter esse evento de jeito nenhum. O servidor decide o valor e paga dentro do código que verificou o roubo:

lua
-- server (ox_lib callback)
lib.callback.register('robbery:finish', function(source, id)
    local state = robberies[id]
    if not state or state.robber ~= source then return false end
    if os.time() - state.started < Config.MinDuration then return false end

    local ped = GetPlayerPed(source)
    if #(GetEntityCoords(ped) - Config.Stores[id].coords) > 5.0 then return false end

    state.busy = false
    state.last = os.time()
    local amount = math.random(Config.Reward.min, Config.Reward.max)
    exports.ox_inventory:AddItem(source, 'money', amount)
    return true
end)

Observe as três verificações: o mesmo jogador começou, tempo suficiente passou, e o jogador ainda está na loja. Distância lado do servidor funciona porque o servidor conhece a posição do jogador com OneSync. Veja securing server events e server callbacks para o padrão.

Atenção: o nome do item para cash depende de sua configuração. Use o item ou a função de framework que seu servidor usa para dinheiro, e mantenha-o no servidor.

Alertando a polícia

Avise os oficiais quando o roubo começar, do servidor, para cada jogador de polícia em duty:

lua
-- server: send to each on-duty officer you found with your police count
TriggerClientEvent('robbery:policeAlert', officerSrc, Config.Stores[id].coords, Config.Stores[id].label)

No cliente, adicione um blip e uma notificação. Você também pode passar o alerta para seu recurso de dispatch em vez de construir o seu próprio, o que dá aos oficiais um único lugar para todas as chamadas. Um pequeno atraso ou uma chance de um alarma silencioso faz o roubo parecer menos scriptado. Blips são cobertos em creating blips.

Erros comuns de config

  • Contagem de polícia definida para 0 enquanto testava, depois deixada assim no servidor ao vivo.
  • Intervalo de recompensa muito alto. Um roubo que paga mais de uma hora de qualquer trabalho é farmado. Compare com seu holerite, como em balancing the server economy.
  • Cooldown muito curto. Com poucas lojas e cooldowns rápidos, os jogadores alternam entre elas.
  • Nenhuma verificação de distância no passo de conclusão, então um jogador pode começar o roubo e coletar de outro lado do mapa.
  • Itens necessários (lockpick, drill) nunca removidos, ou removidos no cliente.
  • Flag ocupado nunca limpo após desconexão ou erro de script.
  • Coordenadas copiadas de outro mapa. Se você usar um MLO ou mapa diferente, a localização da loja está errada.

Teste com uma segunda conta que não é administrador, porque permissões de admin podem ocultar uma verificação faltante.

Lista de verificação

Sintoma Solução
Roubo sem polícia online Conte oficiais em duty no servidor, defina um mínimo acima de 0
Loja roubada novamente imediatamente Adicione um cooldown do servidor codificado por id de loja
Cheater obtém o payout Remova eventos de recompensa do cliente, pague dentro do código do servidor verificado
Payout de longe Verifique distância no servidor no início e fim
Loja trancada para sempre Limpe a flag ocupado ao terminar, falhar e desconectar
Cooldown perdido na reinicialização Armazene o tempo do último roubo no banco de dados

Respostas rápidas

Onde o cooldown de roubo deve ser armazenado?

No servidor, em uma tabela codificada por id de loja ou banco. Um cooldown mantido no cliente reseta a cada reconexão e é fácil de pular.

Por que os jogadores ganham dinheiro de roubos sem os fazer?

O evento de recompensa confisa no cliente. Dê a recompensa apenas dentro do código do servidor que começou e verificou o roubo, nunca de um evento que o cliente pode disparar sozinho.

Quantos policiais um roubo deve precisar?

Depende de quantos oficiais seu servidor geralmente tem. Um começo comum é um ou dois para uma pequena loja e mais para um banco, depois ajuste pelo que você vê.

Scripts sem esse problema

CCTV Security CamerasCâmeras posicionáveis, um tablet com várias telas ao vivo e fotos impressas como prova.Ver script →Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →

Continue lendo