Cómo funcionan las integraciones#
Nada dentro del núcleo protegido de Billiards sabe qué framework usas. El dinero, los permisos, los nombres, las notificaciones, el aviso de la mesa y el menú pasan por pequeños archivos puente sin cifrar que puedes editar:
Capa | Compatible | Sin ella |
|---|---|---|
Framework |
| Standalone: todas las mesas son gratis y las apuestas ni se cobran ni se pagan. |
Dinero | Efectivo y banco del framework detectado | Tus propias funciones en la config — consulta Una moneda personalizada. |
Notificaciones |
| Las notificaciones de ox_lib — es obligatorio de todos modos. |
Aviso de la mesa |
| El texto flotante integrado sobre la mesa. |
Menús |
| Obligatorio. |
Base de datos |
| Obligatorio. El único. |
Cada integración opcional se degrada en silencio. Si falta un recurso, esa parte vuelve a la versión integrada — nada da error y no hay que desactivar nada a mano.
Frameworks#
El framework se detecta al iniciar el recurso, buscando un es_extended, qb-core o qbx_core en ejecución. Cada mesa cobra en money (efectivo) o bank, y las apuestas usan Config.Bot.betMethod:
money es el efectivo del jugador (getMoney, removeMoney, addMoney); bank es la cuenta bancaria (getAccount('bank'), removeAccountMoney, addAccountMoney). El nombre que ven los demás jugadores viene de xPlayer.getName(). Archivo puente: server/custom/framework/esx.lua.
money es cash y bank es bank, a través de Player.Functions.GetMoney, RemoveMoney y AddMoney. El nombre que ven los demás jugadores es el nombre y apellido del personaje. Archivo puente: server/custom/framework/qb.lua.
Qbox funciona a través del mismo puente de QBCore, usando la compatibilidad qb-core que proporciona qbx_core — no hay nada que configurar. Mantén qbx_core iniciado antes de qs-billiards.
Sin framework: CanAfford siempre responde que sí y no se mueve dinero, así que todas las mesas son gratis y las apuestas ni se cobran ni se pagan. Los nombres son los nombres de FiveM de los jugadores. Para cobrar a los jugadores de todos modos, define las tres funciones de Una moneda personalizada.
Una moneda personalizada#
Las entradas y las apuestas solo preguntan tres cosas: si este jugador puede pagarlo, cobrarlo y dárselo. Define esas tres en config/config.lua y sustituyen el dinero del framework en todas partes:
-- config/config.lua
-- method is what is being paid in: the table's payment method for an entry fee,
-- Config.Bot.betMethod for a bet. Both are 'money' or 'bank'.
Config.CanAfford = function(src, amount, method)
return exports['my-coins']:GetCoins(src) >= amount
end
Config.RemoveMoney = function(src, amount, method)
exports['my-coins']:RemoveCoins(src, amount)
end
Config.AddMoney = function(src, amount, method)
exports['my-coins']:AddCoins(src, amount)
endComo se pasa method, un mismo conjunto de funciones puede tratar las entradas y las apuestas de forma distinta — por ejemplo, deja tus mesas en money, establece Config.Bot.betMethod = 'bank' y paga cada importe 'bank' en fichas de casino dentro de tus funciones. Solo se ejecutan en el servidor.
Define las tres juntas. Una apuesta se cobra con
RemoveMoneyantes de la partida y se paga conAddMoneycuando termina; con solo las dos primeras, se cobran las apuestas y nunca se paga a los ganadores.
Notificaciones, el aviso y el menú#
client/custom/framework.lua contiene tres funciones. Sustituye el cuerpo de cualquiera de ellas para usar tu propio recurso:
Función | Se llama |
|---|---|
| Para cada mensaje — faltas, resultados, pagos, el creador. |
| En cada frame en que se muestra el aviso [E] sobre una mesa libre. Usa qs-textui cuando está en ejecución; si no, dibuja el texto por sí misma. |
| Para abrir el menú Pool. |
-- client/custom/framework.lua — okokNotify instead of ox_lib
function Notification(msg, type)
local kind = (not type or type == 'inform' or type == 'info') and 'info' or type
exports['okokNotify']:Alert('Pool', msg, 3000, kind)
endEl panel de estado, el panel de espera, la barra de potencia, Match Settings y la invitación para unirse forman parte de la propia interfaz de Billiards. Siguen el idioma que elijas y no dependen de ningún otro recurso.
Permisos#
Quién puede abrir el creador lo decide una función, HasPermission(src), en cada archivo de server/custom/framework/. Por defecto comprueba el ACE indicado en Config.Creator.permission:
-- server/custom/framework/esx.lua
function HasPermission(src)
local perm = Config.Creator and Config.Creator.permission or 'command.poolcreator'
return IsPlayerAceAllowed(src, perm)
endJunto a ella, GetCharacterName(src) decide el nombre que aparece en la invitación para unirse y en Waiting for <name>... — el nombre del personaje en ESX y QBCore, y el nombre de FiveM cuando no devuelve nada.
Mesas del mapa#
GTA V ya tiene mesas de billar — prop_pooltable_02 y prop_pooltable_3b — y muchos mapas y MLOs las colocan en bares y clubes. Con Config.AutoDetect = true, cada jugador busca la mesa más cercana de cada modelo de Config.TableModels en un radio de 60 m, cada 1,5 segundos, y la registra en el servidor. Una sala llena de mesas del mapa se va completando a medida que los jugadores la recorren.
Config.AutoDetect = true
Config.TableModels = { `prop_pooltable_02`, `prop_pooltable_3b` } -- each needs a Config.Surfaces entryLas mesas del mapa usan el prop que ya está en el mapa, cobran Config.PlayPrice en efectivo y ofrecen todos los modos activados. Solo existen en la memoria del servidor y vuelven cada vez que un jugador se conecta. Para darle a una su propio nombre, precio o modos, ábrela en el creador y guárdala.
Los mapas suelen decorar sus mesas con un taco, un triángulo o una bola blanca suelta. Config.HideWorldProps oculta esos modelos a menos de 1,6 m de cada mesa, para que no quede nada sobre el paño:
Config.HideWorldProps = {
enabled = true,
radius = 1.6,
models = { `prop_pool_cue`, `prop_pool_tri`, `prop_poolball_cue` },
}Añadir un modelo de mesa#
Se puede jugar en cualquier prop de mesa de billar en cuanto Billiards sabe dónde está su paño. Un modelo sin entrada en Config.Surfaces se ignora en todas partes — nunca aparece y nunca se puede jugar. Si el modelo no forma parte de GTA V, primero haz stream de él desde tu propio recurso.
Describe su paño
Añade una entrada a
Config.Surfaces.offsetes la distancia desde el origen del prop hasta el centro del paño;halfes la mitad del ancho y la mitad del largo de la zona jugable, en metros. Parte de los valores de las mesas incluidas.lua Config.Surfaces = { [`prop_pooltable_02`] = { offset = vec3(-0.060, 0.130, 0.900), half = vec2(0.790, 1.380) }, [`prop_pooltable_3b`] = { offset = vec3(0.000, 0.000, 0.900), half = vec2(0.790, 1.380) }, [`my_pool_table`] = { offset = vec3(0.000, 0.000, 0.900), half = vec2(0.790, 1.380) }, }Ofrécelo
Añádelo a
Config.Creator.modelspara verlo en el creador, y aConfig.TableModelssi quieres que se detecten sus copias en tus mapas.lua Config.Creator = { permission = 'command.poolcreator', models = { { hash = `prop_pooltable_02`, label = 'Classic Green Pool Table' }, { hash = `prop_pooltable_3b`, label = 'Classic Purple Pool Table' }, { hash = `my_pool_table`, label = 'Tournament Table' }, }, -- ... }Calíbralo
Coloca uno y luego sigue Calibrar una mesa personalizada:
/pooledity/pooltuneimprimen los valores exactos deoffsetyhalfpara volver a pegarlos.
Idiomas#
Se incluyen cuarenta y una traducciones completas en locales/, y un solo ajuste elige el idioma de las notificaciones, el aviso y toda la interfaz — el creador, Match Settings y la invitación para unirse:
-- ar, bg, bn, ca, cs, da, de, el, en, es, et, fa, fi, fr, he, hi, hr, hu, id, it, ja,
-- ko, lt, lv, ms, nl, no, pl, pt, ro, ru, sk, sl, sv, sw, th, tr, uk, ur, vi, zh
Config.Locale = 'en'Cualquier texto se puede reformular en locales/<code>.json, en su sección billard. Un código que no existe vuelve al inglés, y también cualquier clave que falte en tu archivo — la consola nombra cada una, así que es fácil completar una traducción parcial.



