Scripts de robo de tienda y banco en FiveM: configuración y diseño del lado del servidor
Cómo configurar y diseñar robos de tienda y banco en FiveM: conteo de policías, cooldowns del lado del servidor, recompensas dadas solo por el servidor, alertas de policía y comprobaciones de distancia.
El síntoma: los jugadores roban una tienda sin policía en línea, la misma tienda se roba diez veces seguidas, o un tramposo dispara un evento y obtiene el pago completo.
Un script de robo es una pequeña máquina de estado del lado del servidor: verifica las reglas, comienza, espera, paga. La mayoría de los exploits vienen de poner esos pasos en el cliente. Este artículo cubre un diseño seguro y los errores de config que causan los problemas de arriba.
El flujo que quieres
Piensa en cada robo como cuatro pasos, y ejecuta los pasos 1, 2 y 4 en el servidor:
- Solicitud de inicio: el cliente pide robar una tienda. El servidor comprueba conteo de policía, cooldown, distancia y que nadie esté robándola ya.
- Bloqueo: el servidor marca la tienda como siendo robada y establece el cooldown.
- Acción: el cliente juega la barra de progreso, el hack o el desbloqueo.
- Fin: el cliente reporta hecho, el servidor comprueba el tiempo que ha pasado y la distancia de nuevo, luego paga.
El cliente solo maneja los visuales. Nunca decide el resultado.
Conteo de policía
Requiere un número mínimo de oficiales en turno, contados en el servidor. Un script que lee el conteo desde el cliente, o desde un valor que el cliente envía, es trivial de omitir. El código de conteo está en configurando un trabajo de policía. Compruébalo cuando comienza el robo, y decide si debe comprobarse de nuevo antes del pago.
Cooldowns almacenados en el servidor
Mantén el estado en una tabla del servidor, keyada por el id de ubicación:
-- 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
endDos detalles importan:
- Una tabla en memoria se reinicia cuando el recurso se reinicia. Si quieres que el cooldown sobreviva a un reinicio, almacena la última hora de robo en la base de datos.
- Establece
busycuando comienza el robo y limpialo cuando termina o cuando el ladrón se desconecta, o la tienda se queda bloqueada para siempre.
Recompensas solo desde el servidor
El exploit más común es un evento de recompensa que el cliente puede disparar por su cuenta:
-- WRONG: any client can fire this
RegisterNetEvent('robbery:reward', function(amount)
exports.ox_inventory:AddItem(source, 'money', amount)
end)La solución es no tener ese evento en absoluto. El servidor decide la cantidad y paga dentro del código que verificó el robo:
-- 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)Ten en cuenta las tres comprobaciones: el mismo jugador lo inició, ha pasado suficiente tiempo, y el jugador sigue en la tienda. La distancia del lado del servidor funciona porque el servidor conoce la posición del jugador con OneSync. Ver asegurando eventos del servidor y callbacks del servidor para el patrón.
Cuidado: el nombre del objeto para efectivo depende de tu configuración. Usa el objeto o la función de framework que tu servidor usa para dinero, y guárdalo en el servidor.
Alertando a la policía
Dile a los oficiales cuando comienza el robo, desde el servidor, a cada jugador de policía en turno:
-- 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)En el cliente, añade un blip y una notificación. También puedes entregar la alerta a tu recurso de despacho en lugar de construir el tuyo, lo que da a los oficiales un solo lugar para todas las llamadas. Un pequeño retraso o una chance de alarma silenciosa hace que el robo se sienta menos scriptado. Los blips están cubiertos en creando blips.
Errores de config comunes
- Conteo de policía establecido en 0 mientras pruebas, luego dejado así en el servidor en vivo.
- Rango de recompensa demasiado alto. Un robo que paga más que una hora de cualquier trabajo se granjea. Compara con tu salario, como en equilibrando la economía del servidor.
- Cooldown muy corto. Con algunas tiendas y cooldowns rápidos, los jugadores rota entre ellas.
- Sin comprobación de distancia en el paso de finalización, así un jugador puede comenzar el robo y cobrarlo desde el otro lado del mapa.
- Objetos necesarios (ganzúa, taladro) nunca removidos, o removidos en el cliente.
- Bandera ocupada nunca limpiada después de una desconexión o un error de script.
- Coordenadas copiadas de otro mapa. Si usas un MLO o mapa diferente, la ubicación de la tienda es incorrecta.
Prueba con una segunda cuenta que no sea admin, porque los permisos de admin pueden ocultar una comprobación faltante.
Checklist
| Síntoma | Solución |
|---|---|
| Robo sin policía en línea | Cuenta oficiales en turno en el servidor, establece un mínimo por encima de 0 |
| Tienda robada de nuevo inmediatamente | Añade un cooldown del servidor keyado por id de tienda |
| El tramposo obtiene el pago | Elimina eventos de recompensa del cliente, paga dentro del código del servidor verificado |
| Pago desde lejos | Comprueba distancia en el servidor al inicio y fin |
| Tienda bloqueada para siempre | Limpia la bandera ocupada al finalizar, fallar y desconectarse |
| Cooldown perdido al reiniciar | Almacena la última hora de robo en la base de datos |
Respuestas rápidas
¿Dónde debería almacenarse el cooldown del robo?
En el servidor, en una tabla keyed por el id de tienda o banco. Un cooldown guardado en el cliente se reinicia en cada reconexión y es fácil omitir.
¿Por qué los jugadores obtienen dinero de robos sin hacerlos?
El evento de recompensa confía en el cliente. Da la recompensa solo dentro del código del servidor que inició y verificó el robo, nunca desde un evento que el cliente puede disparar solo.
¿Cuánta policía debería necesitar un robo?
Depende de cuántos oficiales tu servidor usualmente tiene. Un inicio común es uno o dos para una tienda pequeña y más para un banco, luego ajusta de lo que ves.
Scripts que evitan este problema
CCTV Security CamerasCámaras colocables, una tablet con vista múltiple en vivo y fotos como prueba.Ver script →
Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →
Shop CreatorCrea una tienda en menos de un minuto — dueños, empleados, caja fuerte y atracos.Ver script →