Interact system
Sistema de interação 3D + engine de diálogo de NPC, sem nenhuma dependência. Coloque uma interação em qualquer lugar do mapa: numa entity, numa coordenada qualquer, ou num NPC que você spawna na mesma chamada. Sem ox_lib, sem framework, nada para configurar do lado do servidor.
O que ele faz
Nenhuma dependência
Desde a 1.1.0 o resource traz o próprio tratamento de DUI, os pontos de proximidade e os helpers de espera em `bridges/compat.lua`, escritos direto em natives. Nada para instalar antes, nenhuma ordem de carregamento para se preocupar. Se você já roda ox_lib e prefere deixar esse trabalho com ele, coloque `Config.UseOxLib = true` e descomente uma linha no manifest.
Especificações
técnicas
Tudo o que
você recebe
-
Quinze arquivos de idioma, entregues preenchidos
Seus jogadores leem o script no idioma deles desde o primeiro start, e os arquivos ficam fora do escrow, então você corrige qualquer linha em produção. Nota honesta: eles são traduzidos e revisados por nós, não revisados por nativos dos quinze idiomas. Diga o que soa errado no seu e a gente corrige.
-
Tudo se ajusta no config.lua
Rótulo, tecla, distâncias, ícone e cor padrão de um ponto, cores nomeadas, a correspondência entre rótulo de tecla e índice de controle, o ped usado quando uma entrada não informa nenhum, a distância de spawn, e `Config.Hud` para escolher qual HUD some durante um diálogo. Tudo isso saiu do escrow na 1.1.0.
-
Três exemplos que funcionam
Um watcher de caixas eletrônicos registrado por hash de modelo com menu de duas teclas, um NPC com diálogo ramificado completo e waypoint no GPS, e um ponto de dança com várias teclas. Arquivos reais em `config/`, apague quando os seus estiverem prontos.
-
Suporte no Discord e updates vitalícios
Acesso ao canal de suporte, e todas as atualizações futuras sem custo extra. Sem plano premium, sem addon pago.
Guia de integração
Instalação
-
Coloque o resource
Baixe o script pela sua conta Tebex e copie a pasta
avenida_interact/pararesources/[avenida]/no seu servidor. -
Ative no server.cfg
Adicione
ensure avenida_interact. Nada precisa subir antes: desde a 1.1.0 o resource não tem dependência, então a ordem de carregamento não importa. -
Defina seus padrões
Abra
config/config.luae ajuste o que vale para todos os pontos: rótulo, tecla, distânciasshowIconecanInteract, ícone, cor, cores nomeadas, distância de spawn dos peds, eConfig.Hudpara escolher qual HUD some durante um diálogo. -
Apague as demos
Os exemplos em
config/entities/,config/peds/econfig/positions/ficam ativos enquanto os arquivos estiverem lá. Apague os que não quiser, o manifest varre essas pastas, não tem mais nada para editar. -
Teste o hot reload
Suba o servidor e digite
/restart avenida_interactno jogo. Os ícones somem e voltam limpos, e os pontos registrados pelos seus próprios resources sobrevivem, sem você precisar reiniciar a sua sessão.
Início rápido
Seu primeiro ponto de interação em 30 segundos
Crie um `myscript/client.lua` no seu próprio resource e cole isto. Um marcador ciano aparece a 30m, o prompt "E - Hello" abre a 2m. A única coisa que precisa estar rodando é o próprio 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,
})Referência da API
Exports públicos agrupados por domínio. Cada linha mostra a assinatura da chamada e o que ela faz, não como faz.
Interact Points
positionRegister
exports.avenida_interact:positionRegister(cfg) --> idRegistra um ponto em coordenadas fixas. Aceita todos os campos visuais (
hintIcon,hintColor,showIcon,canInteract,offsetZ,blips) maischoices[]para várias teclas no mesmo ponto.canInteractaceita um número ou uma função, então você pode travar o prompt num emprego, num item ou num cooldown. Retorna um id.pedRegister
exports.avenida_interact:pedRegister(cfg) --> idSpawna um NPC configurado (modelo,
animDicteanimNameou um scenario, blip), pendura um ponto nele e retorna o índice. O ped é invencível, não foge e não cai em ragdoll. Ele nasce e some no raio deConfig.PedSpawnRange, 50m por padrão. ColoquerandomComponents = falsenum vendedor com nome, senão cada jogador vê uma roupa diferente.pedRemove
exports.avenida_interact:pedRemove(idx)Adicionado na 1.1.0. Despawna um ped registrado com
pedRegistere apaga o registro dele, então um NPC de missão temporário pode ir embora quando a missão acaba.entityRegister
exports.avenida_interact:entityRegister(cfg) --> idPendura um ponto numa entity existente, passada em
cfg.entity. Suportacfg.bonepara prender o prompt num bone em vez do centro da entity. Serve para o que outro script já spawnou: um veículo, um prop colocado, um item largado.entityRegisterByHash
exports.avenida_interact:entityRegisterByHash(hash, cfg)Watcher passivo: a config vale para toda entity daquele modelo, as já carregadas e as que aparecerem depois. Uma única thread cobre todos os hashes registrados e faz uma varredura a cada 5s. É isso que você quer para caixas eletrônicos, máquinas de venda e portas, em vez de ficar mantendo uma lista de coordenadas.
entityRemove
exports.avenida_interact:entityRemove(idx)Solta o ponto que o
entityRegisterdevolveu. A entity em si não é tocada.interactCreate
exports.avenida_interact:interactCreate(cfg) --> idPonto em runtime, criado e removido sob demanda. Use quando o ponto só existe por um tempo: um objetivo de missão, uma mochila no chão, um corpo para revistar.
interactRemove
exports.avenida_interact:interactRemove(id)Remove um ponto criado por
interactCreate, junto com o blip dele se ele tiver declarado um.unlockLastInteract
exports.avenida_interact:unlockLastInteract()Um ponto se tranca depois de usado, para que uma tecla segurada não dispare duas vezes. Chame isto no fim da sua ação para rearmá-lo. Se o jogador ainda estiver perto, o prompt volta na hora, senão ele espera o jogador chegar perto de novo.
Prompt API
HandleTextUI
exports.avenida_interact:HandleTextUI(id, data) --> duiHandlerCria ou atualiza uma bolha 3D autônoma, sem nenhum ponto de interação por trás. Para quando você quer controlar a visibilidade pela sua própria thread. Retorna o handler que você passa para o
Draw3DSprite.Draw3DSprite
exports.avenida_interact:Draw3DSprite({ duiHandler, coords, maxDistance, hintOnly? })Desenha a bolha no mundo a partir de uma thread de render, corrigida conforme a proporção da tela. Com
hintOnly = truesó o marcador é desenhado, que é o estado de longa distância de um ponto normal.CloseTextUI
exports.avenida_interact:CloseTextUI(id)Esconde uma bolha, mas mantém o DUI dela na memória, então reabrir é instantâneo.
RemoveTextUI
exports.avenida_interact:RemoveTextUI(id)Remove uma bolha de vez e libera o DUI dela. Use quando souber que ela não vai voltar.
RemoveTextUIs
exports.avenida_interact:RemoveTextUIs()Remove todas as bolhas ativas. O resource chama isso sozinho quando ele para.
IsDuiVisible
exports.avenida_interact:IsDuiVisible() --> booleanVerdadeiro enquanto tem um prompt na tela. Leia isso para os seus próprios prompts não empilharem em cima de uma interação.
Key handler
HandleHoldTextUI
exports.avenida_interact:HandleHoldTextUI(id, data) --> duiHandlerA camada em que os pontos são construídos: ela desenha um prompt em
Coordse fica de olho na tecla dele numa thread manager a 50ms.datarecebeBindToHold(índice de controle),DistanceHold,Coords,ChoicesUIeChoicesCtrlpara um prompt de várias teclas,onCallback(id)ecanInteract(id, dist). Dispara ao apertar, com debounce de 500ms, e o seu callback roda numpcall, então um erro do seu lado não quebra o prompt.CloseHoldTextUI
exports.avenida_interact:CloseHoldTextUI(id)Esconde o prompt sem destruir a instância, para uma saída limpa quando o jogador sai da zona.
RemoveHoldTextUI
exports.avenida_interact:RemoveHoldTextUI(id)Destrói uma instância e libera o DUI dela.
RemoveHoldTextUIs
exports.avenida_interact:RemoveHoldTextUIs()Destrói todas as instâncias ativas.
Receitas
Exemplos de copiar e colar para os casos mais comuns. Você cola na sua resource, ajusta os valores e já está em produção.
O caso mais simples: um ponto em coordenadas, com o blip declarado na mesma table. O marcador aparece a 30m, o rótulo a 2m. Cole isso em qualquer arquivo de client do seu resource.
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,
},
})O watcher registra a sua config uma vez por modelo e aplica em todo prop daquele modelo, já carregado ou que apareça depois. Cada escolha leva rótulo, cor e `condition` próprios, então o roubo só aparece quando o seu script de polícia deixa. Atenção ao nome do campo: uma escolha usa `condition`, não `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,
},
},
})
endUm NPC de missão completo: o ped nasce com a animação e o blip dele, e as respostas do diálogo executam o que você quiser, aqui o native `SetNewWaypoint`. `changeDialog` troca o texto e as respostas, então dá para aninhar tão fundo quanto a conversa pedir. `randomComponents = false` mantém a roupa dela igual para todos os jogadores.
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,
},
},
},
})Perguntas frequentes
- Não precisa. Desde a 1.1.0 o `bridges/compat.lua` implementa a criação de DUI, os pontos de proximidade e os helpers de espera em natives puros, e a linha `@ox_lib/init.lua` está comentada no manifest. Se preferir passar pelo ox_lib, coloque `Config.UseOxLib = true` e descomente essa linha. Os dois caminhos são mantidos, o nativo é o padrão.
- Primeiro o alcance: `showIcon` vale 4m por padrão em `Config.Defaults`, o que é curto se você esperava um marcador visível de longe, então passe o seu próprio valor. Segundo, com `entityRegister` a entity precisa existir na hora da chamada, enquanto `entityRegisterByHash` espera por ela, e é isso que você quer para props do jogo. Terceiro, coloque `Config.Debug = true` para ver os erros internos no console do client.
- Uma escolha lê `condition`, não `canInteract`. `canInteract` é o campo do ponto em si, e lá ele aceita um número ou uma função. Dentro de `choices[]` a trava se chama `condition = function() ... end`, e uma escolha cuja condição retorna false simplesmente não é desenhada.
- Qualquer hex como `#22d3ee`, ou um nome de `Config.Colors`, que vem com `red`, `blue`, `green`, `gold`, `purple` e `white`. Essa table está fora do escrow, coloque a paleta do seu servidor nela e use os seus próprios nomes em tudo. Um `hintIcon` desconhecido é desenhado como texto, então um emoji quebra o galho como ícone.
- Isso foi corrigido na 1.1.0. A textura DUI agora está travada em 1920x1080 e é corrigida na hora de desenhar conforme a proporção real da tela, e o ícone não muda mais de tamanho com a distância. As caixas de resposta dos diálogos também ganharam altura acima de 2560x1440. Atualize o resource se você ainda estiver na 1.0.x.
- A posse é rastreada com `GetInvokingResource()`, então um ponto pertence ao resource que chamou o export. Se você registrar a partir de um handler compartilhado que roda no contexto de outro resource, a limpeza segue esse outro resource. Coloque a chamada dentro de uma função do resource dono do ponto. Desde a 1.1.0 os pontos também são apagados quando um resource inicia, então um restart não deixa mais fantasmas.
- Você não precisa ligar em nada: o resource não conhece o seu framework e nunca fala com o seu servidor. Leia o emprego ou o grade do jogador dentro de `canInteract` ou da `condition` de uma escolha, e chame os seus próprios events pelo `onInteract`. Tudo que roda no seu framework roda atrás dessas duas funções, sem precisar mudar nada.
- Medido em 0.00ms em repouso com 100 pontos. O desenho só acontece dentro do alcance `showIcon`, e a checagem das teclas roda a 50ms para as instâncias que estão perto, então milhares de pontos espalhados pelo mapa não custam nada enquanto não estiverem todos empilhados na mesma rua.
O que dizem os compradores
5.0 2 avaliações 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!
DESTAQUE Avenida TeamBarber shop
Uma barbearia encenada de ponta a ponta, com uma câmera que o jogador controla de verdade. O personagem entra, senta na cadeira, e o barbeiro começa a trabalhar enquanto uma câmera orbital enquadra a cabeça. Cabelo, barba, overlays e todo o conjunto de detalhes de pele, com preview em tempo real antes de você gastar um dólar.
DESTAQUE Avenida TeamClothing store
Uma loja de roupas com outfits salvos, guarda-roupas de empresa e um editor que define os preços do catálogo de dentro do jogo. Todos os componentes e todos os props, comprados peça por peça ou como look inteiro, com um registro no servidor que impede qualquer um de vestir o que não pagou.
DESTAQUE Avenida TeamCore Skin (3 in 1)
Barbearia, estúdio de tatuagem e loja de roupas num único resource FiveM. 1615 tatuagens, todos os componentes e props de roupa, a cabeça e a pele por inteiro, espalhados por 36 lojas. Uma interface, uma câmera, um fluxo de compra, e uma coisa só para instalar em ESX, QBCore, vRP ou standalone.