
PVP
Sistema PvP con zonas FFA, zonas Only y partidas de lobby por equipos. Cada zona y cada partida funciona en su propia dimensión. Además hay una clasificación y un marcador de partida. El script crea la tabla por sí mismo.
- ESX Legacy (
es_extended, probado con 1.14) - oxmysql
- OneSync
- En ESX tiene que estar
Config.EnablePVP = true(por defecto) - Para el menú del garaje en mapas de vehículos: esxmenudefault (o tu propio menú mediante
ClientVehicleMenu)
Funciones
- Zonas FFA: todos contra todos. Por zona, armas fijas o las propias armas del jugador. Respawn con chaleco y una breve protección al spawnear.
- Zonas Only: todos tienen las mismas armas, opcionalmente con un vehículo (p. ej. BF 400) en cada spawn.
- Lobbies: equipo A contra equipo B en modo best-of con ronda decisiva. Se pueden elegir mapa, modo (a pie o vehículo), rondas, hasta 3 armas y una contraseña opcional. El propietario puede expulsar, mezclar y disolver.
- Espectar: quien queda eliminado en una ronda mira a los compañeros vivos y cambia con ← →.
- Marcador de partida arriba en el centro y Clasificación con los filtros FFA, Only y Lobby (incluidas victorias y derrotas).
- Protección de armas: las armas fijas solo existen en el PvP. Las armas reales y su munición quedan protegidas.
- Logs de Discord, exports y tus propias funciones para conectar otros scripts.
Instalación
- Pon la carpeta
off_pvpen tu carpetaresources. - Añade en el
server.cfg, después de oxmysql y ESX:
ensure oxmysql
ensure es_extended
ensure off_pvp- Ajusta los puntos PvP, las zonas y los mapas en
config/a tu servidor.
La tabla off_pvp_stats se crea automáticamente en el primer arranque.
Las zonas en config/settings/config.ffa.lua y config/settings/config.only.lua y los mapas en config/settings/config.lobby.lua son solo ejemplos. Revisa todas las posiciones en el juego y pon las tuyas.
Configuración
Los ajustes están en config/settings/: config.lua para todo lo general, config.ffa.lua, config.only.lua y config.lobby.lua para los tres modos.
config/settings/config.lua
| Opción | Predeterminado | Descripción |
|---|---|---|
serverInfo.name | 'OFF SCRIPTS' | Nombre del servidor, se muestra en la interfaz en lugar de «OFF SCRIPTS» |
serverInfo.locale | 'de' | Idioma: de, en, pl, fr, es o it |
serverInfo.color | { 155, 89, 255 } | Color de la UI (RGB) |
serverInfo.design | 3 | Diseño de la interfaz: 1 = Clásico, 2 = Ticket, 3 = Storefront |
blur | true | Fondo desenfocado mientras el menú está abierto |
quitCommand | 'quitffa' | Comando para salir de FFA, Only, lobbies y partidas en curso |
defaultPed | 's_m_y_valet_01' | NPC para puntos sin un ped válido |
points | 1 ejemplo | Puntos PvP en los que E abre el menú (ver abajo) |
marker | ver archivo | Aspecto de los puntos con marker: type, size, alpha, drawDistance |
respawn.seconds | 3 | Tiempo de espera hasta el respawn en FFA y Only |
respawn.protection | 3 | Segundos de invulnerabilidad tras el spawn |
respawn.armour | 100 | Chaleco tras el spawn |
killHeal | true | Vida y chaleco al máximo tras cada kill (FFA, Only y Lobby) |
leaderboardSize | 50 | Cuántos jugadores muestra la clasificación por modo (3–500) |
Puntos PvP (points):
| Campo | Descripción |
|---|---|
id | Nombre único del punto |
label | Nombre en el texto de ayuda y en el blip |
position | vec4(x, y, z, heading) |
interaction | 'ped' = NPC, 'marker' = marker en el suelo |
ped | Modelo del NPC, sin modelo válido se usa defaultPed |
scenario | Animación del NPC (opcional) |
blip | { sprite, color, scale }, false = sin blip |
config/settings/config.ffa.lua y config/settings/config.only.lua
Config.ffa y Config.only contienen las zonas. Cada zona tiene:
| Campo | Descripción |
|---|---|
id | Nombre único, a la vez el nombre de la imagen: web/dist/assets/maps/<id>.png |
label | Nombre en el menú |
center | Centro de la zona, vec3 |
radius | Radio en metros. Quien sale de él va a un spawn aleatorio |
maxPlayers | Jugadores a la vez |
spawns | Lista de vec4. En el respawn se usa el spawn más alejado de los demás jugadores |
weapons | { name, ammo }. FFA: opcional, sin lista se lucha con las armas propias y se gasta munición real. Only: obligatorio |
vehicle | Solo Only, opcional: { model, label }. Se spawnea sobre este vehículo |
config/settings/config.lobby.lua
Config.lobby contiene los ajustes de los lobbies:
| Opción | Predeterminado | Descripción |
|---|---|---|
maxPlayers | 10 | Jugadores por lobby, como máximo la mitad por equipo |
maxLobbies | 8 | Lobbies a la vez |
maxWeapons | 3 | Armas que se pueden elegir al crear |
rounds | 1 / 15 / 5 | Rondas: min, max y default |
prepareSeconds | 3 | Preparación antes de cada ronda (congelado, sin armas), en la primera ronda 3 segundos más |
roundEndSeconds | 1 | Pausa tras una ronda |
resultSeconds | 1 | Muestra del resultado, después se vuelve |
roundMinutes | 5 | Límite de tiempo por ronda, 0 = sin límite |
spectateDelay | 3 | Segundos tras la muerte hasta espectar |
startRange | 50.0 | Lo cerca de un punto PvP que deben estar todos los miembros al empezar |
overtimeRounds | 1 | Rondas decisivas en caso de empate, 0 = empate |
armour | 100 | Chaleco al inicio de cada ronda |
weapons | 10 armas | Armas a elegir al crear: { name, ammo } |
vehicles | 3 vehículos | Vehículos por defecto para mapas de vehículos sin lista propia: { model, label } |
Config.maps contiene los mapas de los lobbies:
| Campo | Descripción |
|---|---|
id / label | Nombre único (= nombre de la imagen, como en las zonas) y nombre visible |
mode | 'foot' = a pie, 'vehicle' = mapa de vehículos |
center / radius | Esfera que se muestra en la partida (vec3 y metros). Solo es visual, no hay límite |
vehicles | Opcional, lista propia de vehículos { model, label }. Sin lista se usa Config.lobby.vehicles |
teams.a / teams.b | Un spawn (vec4) por equipo. Todos los jugadores del equipo empiezan allí cada ronda |
garage / vehicleSpawn | Solo mapas de vehículos, por equipo: marker del garaje (vec3) y punto de salida (vec4) |
config/functions.lua
Aquí conectas tus propios scripts. Los errores en ellas llegan a la consola, el script sigue funcionando. kind siempre es 'ffa', 'only' o 'lobby'.
| Función | Lado | Para qué |
|---|---|---|
ServerCanJoin(source, kind, id) | Servidor | return false, 'Text' impide unirse e iniciar el lobby, p. ej. en la cárcel |
ServerKill(killer, victim, kind, id) | Servidor | Kill contado, p. ej. dinero como recompensa |
ServerDeath(victim, killer, kind, id, teamkill) | Servidor | Cada muerte, killer puede ser nil |
ServerMatchEnded(lobbyId, result) | Servidor | Partida terminada: { winner, score, map, teams }, winner = 'a', 'b' o nil |
ServerJoined(source, kind, id) | Servidor | El jugador entra en una zona o una partida |
ServerLeft(source, kind, id, reason) | Servidor | reason = 'quit', 'drop', 'end', 'kick' o 'stop' |
Notify(message, type) / HelpNotify(text) | Cliente | Notificación y texto de ayuda · Servidor: Notify(source, message, type) |
ClientRevive(position) | Cliente | Revivir, p. ej. tu propio script de ambulancia |
ClientDeath(kind) / ClientRespawn(kind) | Cliente | Muerte y respawn en el PvP, p. ej. ocultar la pantalla de muerte |
ClientGiveLoadout(loadout) | Cliente | Dar y devolver armas |
ClientSetFuel(vehicle, fuel) | Cliente | Script de combustible |
ClientVehicleSpawned(vehicle, plate, kind) | Cliente | Vehículo PvP spawneado, p. ej. dar llaves |
ClientVehicleMenu(vehicles, onSelect) | Cliente | Menú del garaje en mapas de vehículos (por defecto: menú ESX Default) |
ClientStateChanged(state) | Cliente | { kind, id, team } al entrar, nil al salir, p. ej. bloquear el móvil o tu propio HUD |
config/settings/config.server.lua e idiomas
Webhooks de Discord para lobby (lobby creado, partida iniciada, partida terminada, lobby disuelto) y zones (entrar y salir de una zona). '' desactiva un log. Todos los textos están en config/locales/ (un archivo por idioma).
En el juego
- Menú: E en un punto PvP. Solo funciona vivo, a pie, en la dimensión normal y fuera del gangwar.
- FFA y Only: Unirse te teletransporta a la zona. Tras morir, sigues en un spawn después de
respawn.seconds. Arriba ves kills, muertes y los jugadores de la zona. - Salir:
/quitffa(o tuquitCommand) te lleva de vuelta al sitio donde te uniste. Vida y chaleco quedan como antes, tus propias armas vuelven. El comando también te saca de un lobby en espera. - Crear lobby: elige mapa, modo, rondas, armas y, si quieres, una contraseña. Los jugadores nuevos van al equipo más pequeño. Cambiar de equipo es posible mientras el otro no esté lleno. Tras 5 contraseñas incorrectas, el lobby queda bloqueado para ti durante 60 segundos.
- Propietario: inicia, mezcla, expulsa y disuelve. Si el propietario se va, el siguiente miembro toma el control.
- Inicio: quien esté muerto, en otra dimensión, en el gangwar o más lejos que
startRangede un punto PvP sale del lobby. Cada equipo necesita al menos un jugador. - Partida:
- Cada ronda empieza con la preparación (congelado, sin armas), después hay armas y chaleco.
- Gana una ronda quien elimina a todo el equipo rival. Dentro de una ronda no hay respawn. Si los dos últimos caen a la vez, nadie se lleva el punto.
- Si se acaba el tiempo, gana el equipo con más jugadores vivos, en caso de empate nadie se lleva el punto.
- Gana la partida quien primero consigue más de la mitad de las rondas. Si se han jugado todas las rondas, gana el marcador más alto. En caso de empate hay rondas decisivas (
overtimeRounds), después empate. - El fuego amigo está activado. Un teamkill cuenta como muerte, no como kill.
- Quien abandona una partida en curso recibe una derrota. Si después un equipo queda vacío, el otro gana al instante.
- Después todos vuelven a su punto de partida, el lobby sigue abierto y vuelve a esperar.
- Espectar: tras
spectateDelaysegundos miras a un compañero vivo. Abajo en el centro aparecen su nombre y las flechas. ← y → cambian. - Garaje (mapas de vehículos): durante la ronda, E en el marker del garaje de tu equipo abre la lista de vehículos. Cada jugador tiene un vehículo, uno nuevo sustituye al anterior.
- Clasificación: los mejores jugadores por modo (cantidad mediante
leaderboardSize), ordenados por kills. Los valores nuevos aparecen como mucho al minuto, tras una partida al instante.
Para desarrolladores
-- Servidor
local inPvp = exports.off_pvp:IsInPvp(source) -- FFA, Only o partida en curso
local ffa = exports.off_pvp:IsFFA(source)
local only = exports.off_pvp:IsOnly(source)
local lobby = exports.off_pvp:IsLobby(source) -- en una partida en curso
local inLobby = exports.off_pvp:IsInLobby(source) -- miembro de un lobby, esperando o en partida
local info = exports.off_pvp:GetPvp(source) -- { kind, id, team, alive, kills, deaths } o nil
local removed = exports.off_pvp:RemoveFromPvp(source) -- saca al jugador de una zona, partida o lobby en espera, true/false
local stats = exports.off_pvp:GetStats(source) -- { ffa = { kills, deaths }, only = { ... }, lobby = { kills, deaths, wins, losses } } o nil
-- Cliente
local inPvp = exports.off_pvp:IsInPvp()
local ffa = exports.off_pvp:IsFFA()
local only = exports.off_pvp:IsOnly()
local lobby = exports.off_pvp:IsLobby()
local spectating = exports.off_pvp:IsSpectating()
local info = exports.off_pvp:GetPvp() -- { kind, id, team, phase } o nil- Statebag
offPvp:'ffa','only'o'lobby'mientras el jugador esté en una zona o una partida. - offinventory:
canOpen()enoff_inventory/config/functions.luabloquea el inventario y el maletero en el PvP en cuanto offpvp está en marcha.
Problemas frecuentes
Al arrancar, el script muestra errores y avisos en la consola del servidor. Las zonas y mapas con errores aparecen ahí y se ignoran.
| Problema | Solución |
|---|---|
| «Eso no es posible ahora mismo.» al abrir | Estás muerto, en otra dimensión o en el gangwar. |
| Falta una zona o un mapa en el menú | Revisa la consola, la entrada tiene un error (p. ej. sin spawns). |
| No hay imagen en la zona o el mapa | Falta web/dist/assets/maps/<id>.png. |
| El garaje no abre ningún menú | Inicia esxmenudefault o ajusta ClientVehicleMenu. |
| Los jugadores no se hacen daño | Pon Config.EnablePVP = true en ESX. |
| El script de ambulancia muestra la pantalla de muerte en el PvP | Ocúltala en ClientDeath y vuelve a mostrarla en ClientRespawn. |
| En el sitio equivocado tras un crash | En el siguiente login vuelves automáticamente a tu punto de partida. |
| Reinicio del resource durante una partida | Todos vuelven, la partida no cuenta. Mejor no reiniciar durante las partidas. |
¿Aún no lo has comprado?
Ver PVP en la tienda