INSTALLATION GUIDE

Installing Interactions

Quick install — the short version

Everything below, without the walkthrough. Scroll past it if this is your first time.

Or let the page write the lines for you

Drop ox_lib's textui.lua or qb-core's drawtext.lua below. The patched version comes back with every line already in the right place, correctly indented, ready to save over the original.

NOTHING LEAVES YOUR BROWSER — CHECK THE NETWORK TAB
RECOGNISED FILES ox_lib / resource / interface / client / textui.lua qb-core / client / drawtext.lua
OR PASTE IT
Waiting for a file.

Native mode — it is your target system

Native is the default: stop qb-target / ox_target / qtarget and restart the server. Every script keeps calling the same exports — we answer them. Want to keep your own target? Open /dispersia_hub → Interactions → Target mode → Intercept: we only restyle its list. One target system per server, never both.

NEVER RESTART IT ON A LIVE SERVER

Scripts register their targets once, when they start. restart dispersia_interactions empties that list and nothing registers again. Restart the whole server. The console prints a red warning if you forget.

qb-target / ox_targetInteractions
Picks what you look at, not who is closestPartlyYes
No prompts through walls—Yes
Doors, bonnet, boot as separate partsBones by handBuilt in
Rules for vehicles and downed players—Hub + exceptions
Built-in tackle—Yes
Per-player size, position, list length—/interaction
Answers both qb and ox exportsOne of themBoth + qtarget
Idle cost0.01–0.03 ms0.00 ms
Rules → Allow in vehicleOff — no targeting from inside a vehicle.
Rules → In-vehicle exceptionsExceptions that work from a vehicle standing still — a tuner, a drive-up NPC.
Rules → Allow when deadOff — no targeting while dead or in last stand.
Rules → When-dead exceptionsExceptions that work while down — the hospital check-in NPC.
Reach → Aim distanceHow far the camera reaches what you look at. 7.0 m, same as other target systems.

All of these are in /dispersia_hub → Interactions. Exception entries match a resource name, an option name, or the start of the label — e.g. { 'Check in' }.

ak47_lib — one setting, nothing to paste

Scripts built on ak47_lib draw their own prompt box. ak47_lib can hand those prompts to ox_lib, and ox_lib prompts already land on our rail. Open ak47_lib/config.lua and set:

AK47_LIB / CONFIG.LUA
replace the existing Config.TextUI line
Config.TextUI = 'ox'

Needs the two ox_lib lines from the install above. Then restart the whole server. Until it is set, the console and the Hub install check say so: ak47_lib draws its own text UI (Config.TextUI = 'default'). Set to 'ox' or 'custom', they stay quiet.

When something does not work

The things that actually go wrong, and what each one means.

A prompt appears and never goes away
The ox_lib patch is half applied — the show line is in, the hide line is not. Both go in the same file, in two different functions. Your server console says this in as many words: ox_lib text UI is HALF installed (1 of 2 lines found). Add the second line from the block above.
Prompts appear twice — ours and the original
Another prompt or text-UI script is patched into the same place. Only one thing can own the render. Remove the other script’s patch, or switch off the matching interceptor in /dispersia_hub → Interactions → Interceptors so we stay out of its way.
Nothing appears at all
Three causes, in the order worth checking:
  • The block is in the wrong file. It has to go in the file that defines the function, not one that calls it.
  • Interactions starts before ox_lib or your target system. Move ensure dispersia_interactions below them in server.cfg.
  • That interceptor is switched off in /dispersia_hub → Interactions → Interceptors.
Run /interactions_test in game. It draws three sample rows first, so you can see the panel itself is alive, then reports every integration point — read from the real file on the server, not guessed from what the prompt looks like.
Can I keep my own target system?
Yes. Open /dispersia_hub → Interactions → Target mode and pick Intercept, then restart the whole server. Your target keeps doing the aiming and the click; we only redraw its option list in our style.

Or pick Native (the default) and stop your target resource — then we are the target system and answer its exports. Never run both: one target system per server.
Target options show but never clear
The wrapper went somewhere that only sees part of the traffic. In ox_target it must replace the existing local SendNuiMessage = SendNuiMessage line in client/main.lua. In qb-target it must be at the very top of client.lua, above anything that could cache the original.
Prompts reverted to the old style after an update
The update overwrote the file and took the block with it. Every vendor has this problem. The difference is that your console says so on the next boot — it tells “never installed” apart from “was active before, missing now”. Paste the block again.
Syntax error / the file looks corrupted
Use WinSCP for FTP uploads. FileZilla can corrupt files in transfer, and a half-written Lua file fails with a syntax error that looks like a bug in the script. Re-upload with WinSCP before reporting anything.
The resource will not start
Almost always a renamed folder. The resource name is baked into the escrow build, so dispersia_interactions has to stay exactly that — no version suffix, no copy marker. Also confirm the folder sits directly inside resources.
ox_lib behaves strangely after patching
Check for a leftover copy of textui.lua in the same folder — something like textui - backup.lua. ox_lib loads resource/**/client/*.lua as a glob, so a spare copy is loaded too and redefines the same functions. Delete it; do not just rename it.
How do I download what I bought?
From the Cfx.re portal: portal.cfx.re/assets/granted-assets. Make sure you are signed in with the same Cfx.re account you used at checkout — assets are granted to that account, not to your email.
The asset is missing from my Keymaster
Contact Tebex directly — we have no control over asset grants, and Tebex can resend it to your portal: tebex.io/support-customer.
Before you open a ticket
Restart the resource in game and check F8 (client) and the server console. If there is an error, send a screenshot of it — the full line, not a crop. Turn on /dispersia_hub → Interactions → Advanced → Debug and every row carries a [source] tag showing which interceptor produced it, which usually identifies the problem in one screenshot.

Still stuck?Open a ticket in Discord. Include your framework, the console error, and what you already tried.

OPEN A TICKET

API reference

Most servers never open this. If you patched ox_lib (and qb-core on QBCore), every prompt on your server already draws in one style — there is nothing to call.

THE ONLY LINE MOST SERVERS EVER NEED

Showing a prompt from your own script:

anywhere in your client code
exports['dispersia_interactions']:Show('E', 'Open shop')

Each resource owns its own row and cannot overwrite another’s. Hide() clears the one you registered. Everything below is for the rare case where that is not enough.

Full reference — exports, settings, limits

CLIENT EXPORTS

exports['dispersia_interactions']:Show(key, text, ctx?) Show a keyed row. ctx is optional: pass { ctx = 'shop' } when one resource needs several rows at once. Without it the row is keyed by the calling resource.
exports['dispersia_interactions']:Hide(ctx?) Clear the row this resource registered, or the one under that ctx.
exports['dispersia_interactions']:HideAll() Clear every row immediately, whoever registered it. For death, a menu opening, a cutscene.
exports['dispersia_interactions']:ShowPrompt(key, label, coords?) A prompt for scripts with no target system. Pass coords and it hides itself once the player walks past the Hub's Hide distance.
exports['dispersia_interactions']:HidePrompt() Hide it by hand — from onExit, or when the action stops being valid for a reason distance cannot see.
exports['dispersia_interactions']:SetTheme(opts) Restyle at runtime, no restart. Every key optional — pass only what changes.

THE INTEGRATION SURFACE

exports['dispersia_interactions']:Intercept(kind, ...) The one export every inserted line calls. kind is 'textui', 'textuihide', 'qbdrawtext', 'qbhidetext', 'ak47', 'oxtarget' or 'qbtarget'. Returns true when we drew it and false when we did not — so the caller knows whether to continue.
returns false when… the message is an aiming reticle, the kind is unknown, that interception is switched off in the Hub, or anything inside us threw. In every one of those cases the original renders exactly as it always did.
text parsing 'textui' receives the raw ox_lib string and splits it into rows — including several keys in one string.

THEME KEYS — SetTheme(opts)

blurBackdrop blur in px. Default 0 — a blurred layer costs GPU on every frame it is visible, so it ships off.
keyBgL · keyBgRKey box gradient, left and right.
keyBorderKey box right edge — the strongest line in the shape.
tailStart · tailMidThe fading tail behind the label.
textColorLabel colour. Default '#ffffff'.
tailWidthMaximum tail width as CSS. Default '300px'.

TEXT PARSING — ACCEPTED SHAPES

'[E] - Open shop'The common one.
'[E] - Open  [H] - Rob'Several keys in one string — becomes two rows.
'[E] - Open\n[H] - Rob'Same, on separate lines. Literal \n from locale files is handled too.
'E - Open shop'No brackets. Keys up to 6 characters.
anything elseDrawn as-is with key E, rather than dropped.

SETTINGS — /dispersia_hub → Interactions

Target modeNative (default) — we are the target system. Intercept — keep yours, we restyle its list. Off. Needs a full server restart.
Marker before the keyShows what can be interacted with before Left Alt is pressed. Default off — 0.00 ms until the key is pressed.
Prompt rail rowsRows on screen at once. Default 6; the oldest is dropped first.
Confirm key glyphKey label on rows from a target system. Default 'LMB'.
Interceptors → ox_lib text UINeeds both lines in textui.lua.
Interceptors → qb-core DrawTextNeeds the three lines in qb-core/client/drawtext.lua.
Reach → Hide distanceAuto-hide distance for a coords-bound prompt. Default 3.5.
TackleOn by default. Reach, minimum speed, cooldown and down time.
Tackle → Jobs that can tackleJob name or job type, one per row. Default police, sheriff; leo = every police job on QB / QBox; empty = everyone. Checked on the client and the server. While sprinting the key never opens the list.
Advanced → DebugAdds a [source] tag to every row. Leave off on a live server.

COMMANDS & COST

/interactionEach player's own panel: size, position, list length, pointer speed. Saved per player.
/interactions_testDraws three sample rows, then reports every integration point. The verdict is read from the real file on the server, never guessed from what the prompt looks like.
Idle cost0.00 ms with the marker off: nothing searches until the key is pressed.
Distance watcherOne thread, alive only while a coords-bound prompt is on screen, waking every 250 ms. Nothing runs otherwise.
Resource cleanupWhen a resource stops, its rows go with it — automatically, without that resource having to remember.