Documentação

Documentação do Yoga minigame

O minigame de yoga do modo história, tirado da missão e transformado numa atividade de roleplay que qualquer um pode começar. Alinhe os dois marcadores, sustente a postura enquanto o corpo vai entrando nela, e depois inspire e expire nos gatilhos do controle. Três rotinas, quatorze posturas, as animações e os sons de respiração do próprio jogo. E uma pontuação para os seus próprios scripts reagirem.

  • ESX
  • QBCore
  • Qbox
  • vRP
  • Standalone
01

Instalação

  1. Coloque o resource

    Baixe o script pela sua conta Tebex, copie a pasta avenida_yoga/ para o seu diretório de resources e adicione ensure avenida_yoga na config do servidor.

  2. Defina o idioma e as rotinas

    Config.Locale aceita qualquer um dos quinze códigos que vêm em locales/. Config.EnabledMoves decide quais rotinas os jogadores podem começar, e Config.DefaultMove diz qual entra quando nenhuma é informada.

  3. Coloque os seus spots

    As duas coordenadas de Config.Spots são exemplos, troque elas pelas suas. Cada uma leva direção, rotina e um blip que dá para desligar. Uma lista vazia desativa essa parte inteira e a thread dela.

  4. Aponte as notificações para a sua stack

    Config.Notif está em auto e detecta ox_lib, okokNotify, QBCore ou ESX nessa ordem. Force o alvo se você roda vários, ou use o caminho custom de bridges/notif.lua para o seu próprio sistema.

  5. Ligue a recompensa, ou não

    A atividade funciona do jeito que está sem uma linha do seu código. Quando quiser que ela pague algo, escute avenida_yoga:server:sessionCompleted e leia a pontuação. É o único ponto de integração.

02

Configuração

Transformar uma sessão em recompensa

Um event, disparado uma vez no fim. A pontuação já vem calculada: 1 para uma rotina terminada, no máximo 0,4 se ela for abandonada, menos 8 por cento por postura falhada. O que isso vai pagar é escolha sua.

lua
AddEventHandler('avenida_yoga:server:sessionCompleted', function(src, data)
    -- data.move       'warrior' | 'triangle' | 'sunsalutation'
    -- data.completed  true when the routine went to the end
    -- data.posesBest  poses held
    -- data.poses      poses in the routine
    -- data.fails      poses dropped
    -- data.score      0.0 to 1.0

    if not data.completed then return end

    -- your own reward: stress, stamina, a skill, a payout
    local reward = math.floor(250 * data.score)
end)
03

Exports

Server

  • StartYoga
    exports['avenida_yoga']:StartYoga(src, moveKey?) --> boolean

    Começa uma sessão para um jogador a partir do seu próprio código de servidor, na rotina que você nomear ou na padrão. Retorna false quando a rotina é desconhecida ou o jogador já está numa sessão, então um job ou um prop pode reagir em vez de disparar às cegas.

  • IsDoingYoga
    exports['avenida_yoga']:IsDoingYoga(src) --> boolean

    Verdadeiro enquanto o jogador tem uma sessão viva, com a expiração já contada. Útil para bloquear uma ação de job, um teleporte ou uma loja enquanto o minigame está com os controles dele na mão.

Client

  • StartYoga
    exports['avenida_yoga']:StartYoga(moveKey?) --> boolean

    Pede uma sessão ao servidor a partir do código de client. O pedido passa pelo registro do servidor do mesmo jeito, então não é um jeito de escapar do controle de sessão.

  • IsDoingYoga
    exports['avenida_yoga']:IsDoingYoga() --> boolean

    Verdadeiro enquanto o jogador local está numa sessão. O gêmeo no client do export de servidor, para qualquer coisa que precise reagir no mesmo frame.

04

Receitas

Adicionar um spot de yoga no seu mapa

Um spot precisa de coordenadas e direção. O resto é opcional: a rotina que ele começa, o blip, e até se o tapete aparece. Ponha move em random para variar, ou em menu para o jogador escolher.

lua
-- config/config.lua
Config.Spots = {
    {
        coords  = vector3(-1204.02, -1566.28, 3.63),
        heading = 125.0,
        move    = 'menu',
        blip    = { sprite = 311, colour = 2, scale = 0.7 },
    },
}

Começar o yoga por um job ou um prop

Um job de bem-estar, um pátio de cadeia, uma atividade de reabilitação: libere a sessão para o seu jogador sem precisar de comando. Leia o retorno, ele diz se o jogador estava livre para começar.

lua
local started = exports['avenida_yoga']:StartYoga(src, 'sunsalutation')

if not started then
    -- unknown routine, or the player is already in a session
    return
end

Deixar a sessão mais fácil, ou impiedosa

Quatro números carregam a dificuldade inteira. Suba as tentativas e as falhas para um servidor casual, baixe elas para algo mais perto do jogo base. O tempo de respiração presa é o que impede alguém de estacionar no gatilho.

lua
-- config/config.lua
Config.BreathingAttempts = 3      -- missed cycles before a pose fails
Config.MaxFails          = 5      -- failed poses before the session stops
Config.HoldBreathFailMs  = 15000  -- holding the breath longer fails the pose
Config.MouseGain         = 3.0    -- marker sensitivity on mouse and keyboard

Lançar uma rotina agora e o resto depois

Só as rotinas listadas na config podem ser iniciadas, por comando, por export ou por spot. Um servidor pode abrir só com o Guerreiro e liberar as mais longas num evento, sem mexer em mais nada.

lua
-- config/config.lua
Config.EnabledMoves = { 'warrior' }
Config.DefaultMove  = 'warrior'
05

Perguntas

Precisa de framework?

Não. A atividade nunca lê dinheiro, itens, jobs nem identidade, então não existe nada que um framework pudesse entregar. O mesmo arquivo roda em ESX, QBCore, Qbox, vRP, ox_core ou num servidor standalone sem configurar um único bridge. A única parte que sabe do seu framework é a linha de notificação, um arquivo aberto com seis caminhos.

Preciso do ox_lib?

Não, e aqui dá para ser preciso: o ox_lib serve para exatamente uma coisa, o seletor de rotina num spot definido como menu. Sem ele, esse spot começa a rotina padrão. Config.UseOxLib também troca o carregamento de assets entre os helpers do ox_lib e as chamadas nativas, e vem desligado, então o script roda nas nativas por padrão.

Tem banco de dados?

Não tem, e nem arquivo SQL. O servidor guarda as sessões vivas em memória, uma por jogador, com um tempo que limpa as abandonadas. Nada é escrito em lugar nenhum. Se você quiser um histórico por jogador, é para isso que serve o event de fim: você guarda o que te interessa, no seu próprio schema.

Um client modificado consegue forjar uma sessão perfeita?

Não. A sessão é aberta pelo servidor e o resultado é limitado antes de chegar ao seu event: as posturas sustentadas não podem passar da rotina, as falhas não podem passar de trinta, a flag de concluído é uma comparação estrita e a pontuação é recalculada no servidor a partir desses valores limitados. O pior que um client modificado consegue é reportar uma sessão que ele realmente abriu.

O que acontece quando um jogador solta uma postura?

O corpo levanta de volta. O script lê a animação exata que o ped está tocando e escolhe a recuperação correspondente entre as doze que o jogo traz, e quatro delas têm uma variante própria para uma postura solta cedo demais. A postura conta como falhada, e depois de cinco posturas falhadas a sessão para sozinha.

Dá para fazer yoga em qualquer lugar ou só num spot?

Nos dois. O comando funciona em qualquer lugar a pé, e os spots são uma camada opcional em cima, para os lugares que você quiser sinalizar com tapete e blip. Deixe Config.Spots vazio e sobram só o comando e os exports, e a thread de spots nem chega a iniciar.

Funciona no controle?

Sim, e foi pensado primeiro para ele, como no jogo base. Os dois analógicos levam os marcadores e os gatilhos de cima carregam a respiração, com vibração enquanto os dois marcadores estão no alvo. No mouse e teclado a mesma sessão roda no WASD e no mouse, e os avisos na tela mudam sozinhos conforme o que o jogador usou por último.

Quanto custa o script quando ninguém está fazendo yoga?

0.00ms. O loop de sessão só existe enquanto tem uma sessão, e a thread dos spots passa a rodar de segundo em segundo quando não tem nenhum jogador por perto. Sem nenhum spot declarado, essa thread nem começa.

Carrinho
Spirit RP
Discord