Documentation

Yoga minigame documentation

The yoga minigame from story mode, pulled out of the mission and turned into a roleplay activity anyone can start. Line up both markers, hold the pose while the body moves into it, then breathe in and breathe out on the triggers. Three routines, fourteen poses, the real animations and the real breathing sounds. And a score your own scripts can react to.

  • ESX
  • QBCore
  • Qbox
  • vRP
  • Standalone
01

Installation

  1. Drop the resource

    Grab the script from your Tebex account, copy the avenida_yoga/ folder into your resources directory, and add ensure avenida_yoga to your server config.

  2. Set the language and the routines

    Config.Locale takes any of the fifteen codes shipped in locales/. Config.EnabledMoves decides which routines players may start, and Config.DefaultMove the one used when none is given.

  3. Place your spots

    The two coordinates in Config.Spots are examples, replace them with yours. Each one takes a heading, a routine, and a blip you can turn off. An empty list disables the whole feature and its thread.

  4. Point the notifications at your stack

    Config.Notif is on auto and detects ox_lib, okokNotify, QBCore or ESX in that order. Force a target if you run several, or use the custom branch of bridges/notif.lua for your own system.

  5. Hook the reward, or do not

    The activity works out of the box without any of your code. When you want it to pay something, listen to avenida_yoga:server:sessionCompleted and read the score. That is the only integration point.

02

Configuration

Turn a session into a reward

One event, fired once at the end. The score is already computed: 1 for a finished routine, capped at 0.4 for an abandoned one, minus 8 percent per failed pose. What it pays is your call.

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

    Starts a session for a player from your own server code, on the routine you name or on the default one. Returns false when the routine is unknown or the player is already in a session, so a job or a prop can react instead of firing blind.

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

    True while the player holds a live session, expiry included. Useful to block a job action, a teleport or a shop while the minigame owns their controls.

Client

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

    Asks the server for a session from client code. The request still goes through the server registry, so this is not a way around the session guard.

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

    True while the local player is in a session. The client-side twin of the server export, for anything that has to react in the same frame.

04

Recipes

Add a yoga spot to your map

A spot needs coordinates and a heading. Everything else is optional: the routine it starts, the blip, and whether the mat prop is spawned at all. Set move to random for variety, or to menu to let the player choose.

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 },
    },
}

Start yoga from a job or a prop

A wellness job, a prison yard, a rehab activity: give the session without the command. Read the return value, it tells you whether the player was free to start.

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

Make the session easier, or unforgiving

Four numbers carry the whole difficulty. Raise the attempts and the fails for a casual server, lower them for something closer to the base game. The breath timeout is what stops a player from parking on the trigger.

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

Ship one routine now, the rest later

Only the routines listed in the config can be started, by command, by export or by spot. A server can open with Warrior alone and unlock the longer ones as an event, without touching anything else.

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

Questions

Does it need a framework?

No. The activity never reads money, items, jobs or identity, so there is nothing a framework could provide. The same file runs on ESX, QBCore, Qbox, vRP, ox_core or a bare server without a single bridge to configure. The only framework-aware part is the notification line, which is an open file with six branches.

Do I need ox_lib?

No, and here it is easy to be precise: ox_lib is used for exactly one thing, the routine picker on a spot set to menu. Without it, that spot starts the default routine instead. Config.UseOxLib also switches the asset loading between ox_lib helpers and the native calls, and it ships off, so the resource runs on natives by default.

Is there a database?

None, and no SQL file either. The server keeps the live sessions in memory, one per player, with a timeout that clears an abandoned one. Nothing is written anywhere. If you want a player history, that is what the completion event is for: you store what you care about, in your own schema.

Can a modified client fake a perfect session?

No. The session is opened by the server and the result is clamped before it reaches your event: poses held cannot exceed the routine, fails cannot exceed thirty, the completion flag is a strict comparison and the score is recomputed server side from those clamped values. The worst a modified client can do is report a session it really opened.

What happens when a player drops a pose?

The body stands back up. The resource reads the exact animation the ped is playing and picks the matching recovery from the twelve the game ships, with four of them having a separate variant for a pose dropped early. The pose counts as failed, and after five failed poses the session stops on its own.

Can players do yoga anywhere, or only on a spot?

Both. The command works anywhere on foot, and the spots are an optional layer on top for the locations you want to signpost with a mat and a blip. Leave Config.Spots empty and only the command and the exports remain, with the spot thread never starting.

Does it work on a controller?

Yes, and it was built for one first, like the base game. Two sticks aim the markers and the shoulder triggers carry the breathing, with rumble while both markers are on target. On mouse and keyboard the same session runs on WASD and the mouse, and the on-screen prompts change by themselves depending on what the player last used.

What does it cost when nobody is doing yoga?

0.00ms. The session loop only exists while a session is live, and the spot thread parks when no player is near one. With no spots declared at all, that thread never starts in the first place.

Cart
Spirit RP
Discord