Retro Radial
What does rs_radial actually do?
Section titled โWhat does rs_radial actually do?โA: It is an orbit-style radial menu for FiveM with multi-page navigation, runtime API for adding items from other resources, server-side validation, per-player customization (theme / scale / position / sounds), a Vehicle Control bar, predicates, cooldowns, async actions, Discord logging, and an opt-in ox_lib compatibility bridge.
Does rs_radial require ox_lib?
Section titled โDoes rs_radial require ox_lib?โA: No. It has no hard dependencies. ox_lib is optional. If you enable Config.OxLibBridge.enabled = true, third-party scripts that call ox_libโs radial API are forwarded into rs_radial without code changes.
Does it intercept lib.addRadialItem automatically?
Section titled โDoes it intercept lib.addRadialItem automatically?โA: Only when Config.OxLibBridge.enabled = true. The bridge patches the global lib table with addRadialItem, removeRadialItem, registerRadial, hideRadial, and getCurrentRadialId. If real ox_lib is installed, only those radial functions are patched ox_libโs notifications and other features keep working normally.
Do I need pma-voice?
Section titled โDo I need pma-voice?โA: No. pma-voice is unrelated to this resource.
Which frameworks are supported?
Section titled โWhich frameworks are supported?โA: QBCore, Qbox / qbx_core, ESX, or standalone. Config.Framework = 'auto' (default) detects the running framework. In standalone mode, push job/gang data via SetPlayerJob / SetPlayerGang from your own resource.
Which inventories are supported?
Section titled โWhich inventories are supported?โA: ox_inventory, qb-inventory, qbx_core inventory, ESX. A custom mode is supported via Config.Inventory.customHasItem. Items that donโt use reqItems work regardless of which inventory you have.
Where do I add new items?
Section titled โWhere do I add new items?โA: For permanent items: edit Config.Pages in config.lua. For dynamic / per-player / per-session items: call exports['rs_radial']:AddMenuItem(pageId, item) from your own resource. The runtime-API items are auto-cleaned when the owning resource stops.
How do I add a new page?
Section titled โHow do I add a new page?โA: For permanent pages: add a new entry under Config.Pages in config.lua. For runtime pages: call exports['rs_radial']:AddSubMenu(pageId, { label='...', items={...} }). Navigate to it from any item with type='page', targetPage='your_page_id'.
Why is the page label missing on the main page?
Section titled โWhy is the page label missing on the main page?โA: It shouldnโt be the page label is always rendered under the hub on every page. If youโre seeing it missing, force a CEF cache refresh: restart rs_radial in the server console, or press Ctrl+F5 in the F8 NUI dev tools.
Why does the page label look like itโs inside the hub on a 1080p client?
Section titled โWhy does the page label look like itโs inside the hub on a 1080p client?โA: This was a positioning bug in older builds where the labelโs calc() offset placed it inside the hubโs glow halo on certain resolutions. The fix in v1.0.1 anchors the label directly to the hub via top: 100% so it is always rendered below the hub, regardless of viewport / DPI / scale. Make sure the customer has the latest build and has cache-busted.
How do I use Font Awesome icons?
Section titled โHow do I use Font Awesome icons?โA: Set Config.Icons.fontAwesome.enabled = true. This injects Font Awesome from a CDN at NUI boot. Then use iconType='class' and icon='fa-solid fa-shield-halved' on your items. Without enabling the flag, fa-* classes will not render and the F8 console will log a warning.
Can the customer rename the resource folder?
Section titled โCan the customer rename the resource folder?โA: No. The folder must be named exactly rs_radial. If renamed, both server and client print ^1[rs_radial] FATAL: resource folder has been renamed^0 and the script refuses to run. This is intentional it prevents resource-name drift breaking exports and Tebex escrow checks.
Why is app.js so large?
Section titled โWhy is app.js so large?โA: The release build of app.js is intentionally obfuscated (string-array + control-flow flattening + identifier mangling), which roughly doubles the byte size. Cross-file globals (window.RS_ICON, window.RS_ICONS, window.__rsIconOnError, etc.) are preserved by name so the inline onerror handlers and icon registry keep working.
Why arenโt icons.js and custom_icons.js obfuscated?
Section titled โWhy arenโt icons.js and custom_icons.js obfuscated?โA: They are intentionally plain-text so buyers can register their own built-in icons (custom SVG paths, theme variants). app.js is the only file where business logic lives, and thatโs the one thatโs obfuscated.
Whatโs the difference between config.lua and custom_functions.lua?
Section titled โWhatโs the difference between config.lua and custom_functions.lua?โA: config.lua is for declarative settings (pages, items, theme, feature toggles). custom_functions.lua is for code server-specific functions that items can reference with type='customFunction'. Both are customer-editable and escrow-ignored. custom_functions.lua is loaded BEFORE client.lua so itโs available when items are registered.
How do I prevent cheaters from triggering server events directly?
Section titled โHow do I prevent cheaters from triggering server events directly?โA: Set Config.Security.serverSideValidation = true. Every type='server' item is routed through rs_radial:server:dispatch, which re-runs all visibility checks server-side before firing the configured event. For extra safety, also use Config.Security.triggerProtection = true so the server refuses events for items that fail validation.
How do I log item usage to Discord?
Section titled โHow do I log item usage to Discord?โA: Set Config.Logging.enabled = true and provide Config.Logging.webhookUrl. Per-event filters (itemUsed, blocked, securityViolation) let you control what gets logged. Per-item override is available via logging = { webhookUrl = '...' } on individual items.
Can I integrate with my serverโs existing keybinds?
Section titled โCan I integrate with my serverโs existing keybinds?โA: Yes. Config.Controls.openMode = 'hold' or 'toggle', and the actual key binding is configured via FiveMโs keymapper system (players can rebind from the pause menu).
Are there hooks I can listen to?
Section titled โAre there hooks I can listen to?โA: Yes. Listen to AddEventHandler('rs_radial:event:<name>', fn). Client hooks: menuOpened, menuClosed, pageChanged, itemClicked, itemConfirmed, itemCancelled, itemFailed, settingsSaved, vehicleControlUsed, blipToggled. Server hooks: server:dispatched, server:blocked. See docs/development.md for details.