Script di rapina negozio e banca FiveM: configurazione e design lato server

Come configurare e progettare rapine di negozi e banche su FiveM: conteggio della polizia, cooldown lato server, ricompense date solo dal server, avvisi di polizia e controlli di distanza.

Il sintomo: i giocatori rapinano un negozio senza polizia online, lo stesso negozio è rapinato dieci volte di fila, o un cheater attiva un evento e ottiene l'intero pagamento.

Uno script di rapina è una piccola macchina a stati lato server: controlla le regole, inizia, aspetta, paga. La maggior parte degli exploit proviene dal mettere questi passaggi sul client. Questo articolo copre un design sicuro e gli errori di config che causano i problemi sopra.

Il flusso che vuoi

Pensa a ogni rapina come a quattro passaggi, ed esegui i passaggi 1, 2 e 4 sul server:

  1. Richiesta di inizio: il client chiede di rapinare un negozio. Il server controlla il conteggio della polizia, il cooldown, la distanza e che nessuno lo stia già rapinando.
  2. Blocco: il server segna il negozio come rapinato e imposta il cooldown.
  3. Azione: il client riproduce la barra di avanzamento, l'hack o lo scassinamento.
  4. Fine: il client segnala che ha finito, il server controlla il tempo trascorso e la distanza di nuovo, quindi paga.

Il client gestisce solo gli elementi visivi. Non decide mai il risultato.

Conteggio della polizia

Richiedi un numero minimo di ufficiali in servizio, contati sul server. Uno script che legge il conteggio dal client, o da un valore che il client invia, è banale da bypassare. Il codice di conteggio è in configurazione di un lavoro di polizia. Controllalo quando inizia la rapina, e decidi se dovrebbe essere verificato di nuovo prima del pagamento.

Cooldown memorizzati sul server

Mantieni lo stato in una tabella del server, con chiave l'id della posizione:

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

Due dettagli contano:

  • Una tabella in memoria si ripristina quando la risorsa riavvia. Se vuoi che il cooldown sopravviva a un riavvio, memorizza l'ultimo tempo di rapina nel database.
  • Imposta busy quando inizia la rapina e cancellalo quando termina o quando il rapinatore si disconnette, o il negozio rimane bloccato per sempre.

Ricompense solo dal server

L'exploit più comune è un evento di ricompensa che il client può attivare da solo:

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

La correzione è non avere quell'evento del tutto. Il server decide l'importo e paga dentro il codice che ha verificato la rapina:

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)

Nota i tre controlli: lo stesso giocatore l'ha avviato, è passato abbastanza tempo, e il giocatore è ancora nel negozio. La distanza lato server funziona perché il server conosce la posizione del giocatore con OneSync. Vedi protezione degli eventi del server e callback del server per il pattern.

Attenzione: il nome dell'elemento per il contante dipende dalla tua configurazione. Usa l'elemento o la funzione del framework che il tuo server usa per il denaro, e mantienila sul server.

Avviso della polizia

Dì agli ufficiali quando inizia la rapina, dal server, a ogni giocatore di polizia in servizio:

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)

Sul client, aggiungi un blip e una notifica. Puoi anche consegnare l'avviso alla tua risorsa di dispatch invece di costruire la tua, che dà agli ufficiali un unico posto per tutte le chiamate. Un piccolo ritardo o una possibilità di un allarme silenzioso rende la rapina meno scritta. I blip sono trattati in creazione di blip.

Errori comuni di config

  • Conteggio della polizia impostato a 0 durante il test, quindi lasciato così sul server live.
  • Intervallo di ricompensa troppo alto. Una rapina che paga più di un'ora di qualsiasi lavoro viene coltivata. Confronta con il tuo assegno, come in bilanciamento dell'economia del server.
  • Cooldown troppo breve. Con pochi negozi e cooldown veloci, i giocatori ruotano tra di loro.
  • Nessun controllo di distanza al passaggio di fine, quindi un giocatore può iniziare la rapina e raccoglierla da tutta la mappa.
  • Elementi necessari (scassinamento, trapano) mai rimossi, o rimossi sul client.
  • Flag occupato mai cancellato dopo una disconnessione o un errore di script.
  • Coordinate copiate da un'altra mappa. Se usi un MLO o una mappa diversa, la posizione del negozio è sbagliata.

Testa con un secondo account che non è un admin, perché le autorizzazioni dell'admin possono nascondere un controllo mancante.

Elenco di controllo

Sintomo Soluzione
Rapina senza polizia online Conta gli ufficiali in servizio sul server, imposta un minimo superiore a 0
Negozio rapinato di nuovo immediatamente Aggiungi un cooldown del server con chiave l'id del negozio
Cheater ottiene il pagamento Rimuovi gli eventi di ricompensa del client, paga dentro il codice verificato del server
Pagamento da lontano Controlla la distanza sul server all'inizio e alla fine
Negozio bloccato per sempre Cancella il flag occupato al fine, fallimento e disconnessione
Cooldown perso al riavvio Memorizza l'ultimo tempo di rapina nel database

Risposte rapide

Dove dovrebbe essere memorizzato il cooldown della rapina?

Sul server, in una tabella con chiave l'id del negozio o della banca. Un cooldown mantenuto sul client si ripristina ad ogni riconnessione ed è facile da saltare.

Perché i giocatori ottengono denaro dalle rapine senza farle?

L'evento di ricompensa si fida del client. Dai la ricompensa solo dentro il codice del server che ha avviato e verificato la rapina, mai da un evento che il client può attivare da solo.

Quanti poliziotti dovrebbe avere bisogno una rapina?

Dipende da quanti ufficiali il tuo server di solito ha. Un inizio comune è uno o due per un piccolo negozio e più per una banca, quindi regola da quello che vedi.

Script senza questo problema

CCTV Security CamerasTelecamere posizionabili, un tablet multi-vista in diretta e foto stampate come prove.Vedi script →Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →

Continua a leggere