Interact system
Sistema de interacción 3D + motor de diálogos para NPC, sin ninguna dependencia. Coloca una interacción en cualquier punto del mapa: en una entity, en unas coordenadas sueltas, o en un NPC que haces aparecer desde la misma llamada. Sin ox_lib, sin framework, nada que configurar en el servidor.
Lo que hace
Sin ninguna dependencia
Desde la 1.1.0 el recurso trae su propio manejo de DUI, sus puntos de proximidad y sus helpers de espera en `bridges/compat.lua`, escritos solo con natives. Nada que instalar antes, ningún orden de carga que respetar. Si ya tienes ox_lib y prefieres dejarle ese trabajo, pon `Config.UseOxLib = true` y descomenta una línea del manifest.
Especificaciones
técnicas
Todo lo que
recibes
-
Quince archivos de idioma, ya rellenados
Tus jugadores leen el script en su idioma desde el primer arranque, y los archivos están fuera del escrow, así que puedes corregir cualquier línea en producción. Nota honesta: están traducidos y revisados por nosotros, pero no los ha corregido un hablante nativo de cada uno de los quince. Dinos qué suena mal en el tuyo y lo arreglamos.
-
Todo se ajusta en config.lua
Etiqueta, tecla, distancias, icono y color por defecto de un punto, colores con nombre, la correspondencia entre etiqueta de tecla e índice de control, el ped que se usa cuando una entrada no indica ninguno, la distancia de aparición, y `Config.Hud` para elegir qué HUD se oculta durante un diálogo. Todo eso salió del escrow en la 1.1.0.
-
Tres ejemplos que funcionan
Un watcher de cajeros registrado por hash de modelo con un menú de dos teclas, un NPC con un diálogo ramificado completo y un waypoint GPS, y un punto de baile con varias teclas. Archivos reales en `config/`, bórralos cuando tengas los tuyos.
-
Soporte Discord y actualizaciones de por vida
Acceso al canal de soporte, y todas las actualizaciones futuras sin coste extra. Sin nivel premium, sin complementos de pago.
Guía de integración
Instalación
-
Coloca el recurso
Descarga el script desde tu cuenta Tebex y copia la carpeta
avenida_interact/enresources/[avenida]/de tu servidor. -
Actívalo en server.cfg
Añade
ensure avenida_interact. No hace falta que cargue nada antes: desde la 1.1.0 el recurso no tiene dependencias, así que el orden de carga da igual. -
Fija tus valores por defecto
Abre
config/config.luay ajusta lo que se aplica a todos los puntos: etiqueta, tecla, distanciasshowIconycanInteract, icono, color, colores con nombre, distancia de aparición de los peds, yConfig.Hudpara elegir qué HUD se oculta durante un diálogo. -
Quita las demos
Los ejemplos de
config/entities/,config/peds/yconfig/positions/siguen activos mientras sus archivos estén ahí. Borra los que no quieras, el manifest recorre esas carpetas, no hay nada más que tocar. -
Prueba la recarga en caliente
Arranca el servidor y escribe
/restart avenida_interacten el juego. Los iconos desaparecen y vuelven limpios, y los puntos registrados por tus propios recursos sobreviven, sin reiniciar tu sesión.
Inicio rápido
Tu primer punto de interacción en 30 segundos
Crea un `myscript/client.lua` en tu propio recurso y pega esto. Un marcador cian aparece a 30m, el prompt "E - Hello" se despliega a 2m. Lo único que tiene que estar activo es avenida_interact.
-- myscript/client.lua
exports.avenida_interact:positionRegister({
coords = vec3(-265.0, -963.6, 31.2),
showIcon = 30.0, -- marker fades in at 30m
canInteract = 2.0, -- label unrolls at 2m
hintIcon = 'interact', -- see the icon list below
hintColor = '#22d3ee', -- hex, or an alias from Config.Colors
message = 'Hello',
bind = 'E',
onInteract = function()
TriggerEvent('chat:addMessage', { args = { 'Hello, world!' } })
end,
})Referencia de la API
Exports públicos agrupados por dominio. Cada fila muestra la firma de la llamada y qué hace, no cómo lo hace.
Interact Points
positionRegister
exports.avenida_interact:positionRegister(cfg) --> idRegistra un punto en unas coordenadas fijas. Acepta todos los campos visuales (
hintIcon,hintColor,showIcon,canInteract,offsetZ,blips) máschoices[]para varias teclas en el mismo punto.canInteractacepta un número o una función, así que puedes condicionar el prompt a un trabajo, un item o un cooldown. Devuelve un id.pedRegister
exports.avenida_interact:pedRegister(cfg) --> idHace aparecer un NPC configurado (modelo,
animDictyanimNameo un scenario, blip), le engancha un punto y devuelve su índice. El ped es invencible, no huye y no cae en ragdoll. Aparece y desaparece a la distancia que marcaConfig.PedSpawnRange, 50m por defecto. PonrandomComponents = falseen un vendedor con nombre, porque si no cada jugador le verá ropa distinta.pedRemove
exports.avenida_interact:pedRemove(idx)Añadido en la 1.1.0. Hace desaparecer un ped registrado con
pedRegistery borra su registro, para que un NPC de misiones temporal pueda irse cuando la misión termina.entityRegister
exports.avenida_interact:entityRegister(cfg) --> idEngancha un punto a una entity existente, pasada en
cfg.entity. Admitecfg.bonepara colgar el prompt de un bone en vez del centro de la entity. Úsalo para lo que otro script haya hecho aparecer: un vehículo, un prop colocado, un objeto tirado.entityRegisterByHash
exports.avenida_interact:entityRegisterByHash(hash, cfg)Watcher pasivo: la config se aplica a todas las entities de ese modelo, las ya cargadas y las que aparezcan después. Un único thread cubre todos los hashes registrados y hace una pasada cada 5s. Es lo que quieres para cajeros, máquinas expendedoras y puertas, en vez de mantener una lista de coordenadas.
entityRemove
exports.avenida_interact:entityRemove(idx)Desengancha el punto devuelto por
entityRegister. La entity en sí no se toca.interactCreate
exports.avenida_interact:interactCreate(cfg) --> idPunto en tiempo de ejecución, que creas y quitas cuando hace falta. Úsalo cuando el punto solo existe un rato: un objetivo de misión, una bolsa en el suelo, un cuerpo que registrar.
interactRemove
exports.avenida_interact:interactRemove(id)Quita un punto creado con
interactCreate, y su blip si declaraba uno.unlockLastInteract
exports.avenida_interact:unlockLastInteract()Un punto se bloquea al usarse, para que una tecla mantenida no lo dispare dos veces. Llama a esto al final de tu acción para rearmarlo. Si el jugador sigue dentro del alcance, el prompt vuelve enseguida. Si no, espera a que se acerque otra vez.
Prompt API
HandleTextUI
exports.avenida_interact:HandleTextUI(id, data) --> duiHandlerCrea o actualiza una burbuja 3D autónoma, sin punto de interacción detrás. Para cuando quieres controlar la visibilidad desde tu propio thread. Devuelve el handler que pasas a
Draw3DSprite.Draw3DSprite
exports.avenida_interact:Draw3DSprite({ duiHandler, coords, maxDistance, hintOnly? })Dibuja la burbuja en el mundo desde un thread de render, corregida según la proporción de la pantalla. Con
hintOnly = truesolo se dibuja el marcador, que es el estado a larga distancia de un punto normal.CloseTextUI
exports.avenida_interact:CloseTextUI(id)Oculta una burbuja pero mantiene su DUI en memoria, así que reabrirla es instantáneo.
RemoveTextUI
exports.avenida_interact:RemoveTextUI(id)Quita una burbuja del todo y libera su DUI. Úsalo cuando sepas que no va a volver.
RemoveTextUIs
exports.avenida_interact:RemoveTextUIs()Quita todas las burbujas activas. Se llama automáticamente cuando el recurso se para.
IsDuiVisible
exports.avenida_interact:IsDuiVisible() --> booleanVerdadero mientras hay un prompt en pantalla. Léelo para que tus propios prompts no se apilen encima de una interacción.
Key handler
HandleHoldTextUI
exports.avenida_interact:HandleHoldTextUI(id, data) --> duiHandlerLa capa sobre la que se construyen los puntos: dibuja un prompt en
Coordsy vigila su tecla desde un thread manager a 50ms.datatomaBindToHold(índice de control),DistanceHold,Coords,ChoicesUIyChoicesCtrlpara un prompt de varias teclas,onCallback(id)ycanInteract(id, dist). Dispara al pulsar con un debounce de 500ms, y tu callback se ejecuta dentro de unpcall, así que un error tuyo no rompe el prompt.CloseHoldTextUI
exports.avenida_interact:CloseHoldTextUI(id)Oculta el prompt sin destruir la instancia, para una salida limpia cuando el jugador deja la zona.
RemoveHoldTextUI
exports.avenida_interact:RemoveHoldTextUI(id)Destruye una instancia y libera su DUI.
RemoveHoldTextUIs
exports.avenida_interact:RemoveHoldTextUIs()Destruye todas las instancias activas.
Recetas
Ejemplos para copiar y pegar en los casos más habituales. Los metes en tu recurso, ajustas los valores y a producción.
El caso más simple: un punto en unas coordenadas, con su blip declarado en la misma tabla. El marcador se ve a 30m, la etiqueta a 2m. Pégalo en cualquier archivo de cliente de tu recurso.
exports.avenida_interact:positionRegister({
coords = vec3(149.5, -1040.4, 29.4),
showIcon = 30.0,
canInteract = 2.0,
hintIcon = 'bank',
hintColor = 'blue',
message = 'Use the ATM',
bind = 'E',
onInteract = function()
TriggerEvent('myserver-banking:openATM')
end,
blips = {
sprite = 277,
color = 2,
scale = 0.8,
text = 'ATM',
display = 4,
},
})El watcher registra tu config una vez por modelo y la aplica a cada prop que coincida, esté ya cargado o aparezca después. Cada opción lleva su etiqueta, su color y su `condition`, así que el atraco solo se muestra si tu script de policía lo permite. Ojo con el nombre del campo: una opción usa `condition`, no `canInteract`.
local ATM_PROPS = {
'prop_atm_01', 'prop_atm_02', 'prop_atm_03', 'prop_fleeca_atm',
}
for _, prop in ipairs(ATM_PROPS) do
exports.avenida_interact:entityRegisterByHash(prop, {
canInteract = 1.2,
offsetZ = 1.0,
hintIcon = 'bank',
hintColor = 'blue',
choices = {
{
bind = 'E',
message = 'Use the ATM',
onInteract = function()
TriggerEvent('myserver-banking:atmUse')
end,
},
{
bind = 'G',
message = 'Rob the ATM',
hintColor = 'red',
condition = function()
return exports['myserver-police']:hasEnoughCops(2)
end,
onInteract = function(entity)
TriggerServerEvent('myserver-robbery:startATM', NetworkGetNetworkIdFromEntity(entity))
end,
},
},
})
endUn NPC de misiones completo: el ped aparece con su animación y su blip, y las respuestas del diálogo ejecutan lo que quieras, aquí el native `SetNewWaypoint`. `changeDialog` reemplaza el texto y las respuestas, así que anidas tan profundo como pida la conversación. `randomComponents = false` mantiene su ropa igual para todos los jugadores.
exports.avenida_interact:pedRegister({
coords = vec4(-1393.81, -1064.09, 3.17, 266.09),
model = 'a_f_y_vinewood_04',
animDict = 'anim@amb@waving@male',
animName = 'ground_wave',
randomComponents = false,
message = 'Talk with Maria',
showIcon = 10.0,
canInteract = 3.0,
hintIcon = 'talk',
hintColor = 'gold',
blips = { sprite = 119, color = 50, text = 'Lumberjack', scale = 0.8 },
dialogue = {
name = 'Maria',
startMsg = 'Hello, are you ready to start your shift?',
elements = {
{
label = 'Yes, where do I start?',
action = function(changeDialog, close)
SetNewWaypoint(-584.01, 5491.59)
changeDialog('The forest is on your GPS now.', {
{ label = 'Got it!', action = function(_, close) close() end },
})
end,
},
{
label = 'I\'ll come back later',
action = function(_, close) close() end,
},
},
},
})Preguntas frecuentes
- No lo necesitas. Desde la 1.1.0 `bridges/compat.lua` implementa la creación de DUI, los puntos de proximidad y los helpers de espera solo con natives, y la línea `@ox_lib/init.lua` está comentada en el manifest. Si prefieres pasar por ox_lib, pon `Config.UseOxLib = true` y descomenta esa línea. Los dos caminos siguen soportados, y el nativo es el que viene por defecto.
- Primero el alcance: `showIcon` vale 4m por defecto en `Config.Defaults`, que se queda corto si esperabas un marcador visible de lejos, así que pasa tu propio valor. Segundo, con `entityRegister` la entity tiene que existir en el momento de la llamada, mientras que `entityRegisterByHash` la espera, que es lo correcto para los props del juego. Tercero, pon `Config.Debug = true` para ver los errores internos en la consola del cliente.
- Una opción lee `condition`, no `canInteract`. `canInteract` es el campo del punto en sí, donde acepta un número o una función. Dentro de `choices[]` el filtro se llama `condition = function() ... end`, y una opción cuya condición devuelve false simplemente no se dibuja.
- Cualquier hex como `#22d3ee`, o un nombre de `Config.Colors`, que viene con `red`, `blue`, `green`, `gold`, `purple` y `white`. Esa tabla está fuera del escrow, añade la paleta de tu servidor y usa tus propios nombres en todas partes. Un `hintIcon` desconocido se dibuja como texto, así que un emoji te sirve de icono puntual.
- Está corregido en la 1.1.0. La textura DUI ahora está fijada a 1920x1080 y se corrige en el dibujado según la proporción real de la pantalla, y el icono ya no cambia de tamaño con la distancia. Las cajas de respuesta de los diálogos también ganaron altura por encima de 2560x1440. Actualiza el recurso si sigues en la 1.0.x.
- La propiedad de un punto se rastrea con `GetInvokingResource()`, así que pertenece al recurso que llamó al export. Si registras desde un handler compartido que se ejecuta en el contexto de otro recurso, la limpieza sigue a ese otro recurso. Envuelve la llamada en una función del recurso dueño del punto. Desde la 1.1.0 los puntos también se purgan al arrancar un recurso, así que un restart ya no deja fantasmas.
- No tienes que conectarlo a nada: el recurso no conoce tu framework y nunca habla con tu servidor. Lee el trabajo o el grado del jugador dentro de `canInteract` o de la `condition` de una opción, y llama a tus propios events desde `onInteract`. Todo lo que funciona con tu framework se queda detrás de esas dos funciones, sin cambios.
- Medido a 0.00ms en reposo con 100 puntos. El dibujado solo ocurre dentro del alcance `showIcon`, y la vigilancia de teclas se ejecuta cada 50ms para las instancias que están dentro del alcance, así que miles de puntos repartidos por el mapa no cuestan nada mientras no estén todos apilados en la misma calle.
Lo que dicen los compradores
5.0 2 opiniones verificadas
Revoria very good scriptwriters a reactive and competent listening team I recommend go there with your eyes closed!!
theara Best script, best support! Fast support and friendly!
DESTACADO Avenida TeamBarber shop
Una barbería puesta en escena, con una cámara que el jugador controla de verdad. El personaje entra, se sienta y el barbero se pone a trabajar mientras una cámara orbital encuadra la cabeza. Pelo, barba, overlays y todos los detalles de piel, con vista previa en directo antes de gastar un solo dólar.
DESTACADO Avenida TeamClothing store
Una tienda de ropa con conjuntos guardados, vestuarios de empresa y un editor que pone precio al catálogo desde el propio juego. Todos los componentes y todos los props, comprados prenda a prenda o como conjunto entero, con un registro en el servidor que impide que nadie lleve puesto lo que no ha pagado.
DESTACADO Avenida TeamCore Skin (3 in 1)
Barbería, estudio de tatuajes y tienda de ropa en un solo recurso FiveM. 1615 tatuajes, todos los componentes y props de ropa, la cabeza y la piel al completo, repartido todo por 36 tiendas. Una interfaz, una cámara, un flujo de compra, y una sola cosa que instalar en ESX, QBCore, vRP o standalone.