Skip to content

BLN Native Wheel ​

bln wheel

πŸ“Ί Preview ​

Video Preview

πŸ’° Buy Now ​

Get it now

Introducing BLN Wheel Menu - a premium radial menu system built using native RedM functions, offering the smoothest and most authentic experience possible. Say goodbye to laggy NUI-based menus and hello to seamless, game-like interaction!

Why Choose BLN Wheel Menu? ​

  • Native Implementation - Built using game natives for that authentic RedM feel
  • Zero NUI Impact - No performance hit from web-based interfaces
  • Pixel-Perfect Recreation - Matches the original game's wheel menu design
  • Unlimited Menu Items - No more 8-item limit, create detailed nested menus
  • Theme System - Swap between 10 built-in themes or create your own
  • Favorites & Hotkeys - Assign items to favorite slots (1-8) and trigger them with a hotkey
  • History Mode - Automatically tracks recently used items for quick access
  • Emotes Menu - Built-in emotes menu with many emotes ready to use
  • Advanced Filtering System - Control access to menu items based on any condition
  • Complete Controller Support - Full keyboard, mouse and controller navigation support
  • Hybrid Input System - Seamless switching between mouse and keyboard/controller

Quick Setup ​

  1. Add to your resources folder
  2. Add ensure bln_wheel to your server.cfg (after bln_lib and bln_notify)
  3. Configure your menu items in shared/menu.lua
  4. Pick a theme in shared/config.lua
  5. Enjoy!

Configuration ​

Config File (shared/config.lua) ​

The config file handles behavior and logic settings. All visual/UI settings are managed through the theme system.

lua
Config = {
    showMode = 'hold',        -- 'toggle' or 'hold'
    zoomEffectEnabled = true, -- Enable zoom effect when menu is shown

    keys = {
        toggle = 0x8AAA0AD4, -- LEFT ALT - to show/hide the menu
        left = 0xD0842EDF,   -- Wheel down (scroll)
        right = 0xF78D7337,  -- Wheel up (scroll)
        select = 0xCEFD9220, -- E
        back = 0x156F7119,   -- BACKSPACE
        favorite = 0x7F8D09B8, -- V - Remove favorite
        help = 0x4CC0E2FE,    -- B - Show help
        modifier = 0x8FFC75D6, -- LEFT SHIFT - modifier for hotkey slots
    },

    slotAssignHoldTime = 1000, -- ms to hold number key to assign to slot

    promptLabels = {
        back = "Back",
        switch = "Switch Mode",
        favorite = "Remove Favorite",
        help = "Help",
    },

    theme = 'default', -- Theme name from shared/themes.lua
}

Theme System (shared/themes.lua) ​

All visual and UI settings are defined in themes. Set Config.theme to any theme name to apply it.

To customize, either modify an existing theme directly in shared/themes.lua or create a new one.

Theme Structure ​

Each theme contains:

lua
['my_theme'] = {
    fontId = 7, -- Font index (https://docs.bln-studio.com/docs/resources.html#text)
    colors = {
        itemBg = { r = 0, g = 0, b = 0, a = 200 },        -- Segment background
        itemIcon = { r = 255, g = 255, b = 255, a = 255 },  -- Default icon color (per-item color overrides)
        centerBg = { r = 0, g = 0, b = 0, a = 100 },        -- Center circle background
        centerText = { r = 255, g = 255, b = 255, a = 255 }, -- Center text & icon color
        progress = { r = 219, g = 2, b = 2, a = 255 },      -- Hold-to-assign progress bar
        itemArrow = { r = 219, g = 2, b = 2, a = 255 },     -- Hover indicator overlay
        header = {
            bg = { r = 0, g = 0, b = 0, a = 200 },              -- Mode tabs background
            text = { r = 255, g = 255, b = 255, a = 127 },      -- Inactive tab text
            textHover = { r = 255, g = 255, b = 255, a = 255 },  -- Active/hovered tab text
        },
        onHover = {
            itemBg = { r = 219, g = 2, b = 2, a = 255 },        -- Segment bg when hovered
            itemIcon = { r = 255, g = 255, b = 255, a = 255 },   -- Icon color when hovered
            centerText = { r = 219, g = 2, b = 2, a = 255 },     -- Center text when hovering item
        }
    }
}

Available Themes ​

ThemeDescription
defaultClassic dark with red accents
western_sunsetWarm brown with orange highlights
night_skyMidnight blue with violet accents
forestDark green with olive highlights
desert_sandSaddle brown with tan accents
stealthDark gray with subtle silver
royalDeep blue with gold accents
emberMaroon with orange fire accents
ocean_deepDeep blue with teal highlights
purple_duskDark purple with lavender accents

Applying a Theme ​

In shared/config.lua:

lua
Config = {
    theme = 'western_sunset', -- Change this to any theme name
}

Controls ​

Keyboard & Mouse ​

ActionKey
Open/Close menuLEFT ALT (hold or toggle)
Browse itemsScroll Wheel / Mouse movement
Select itemE
Go backBACKSPACE
Switch modeR
Remove favoriteV (hold)
Show helpB
Assign to hotkey slotHold 1-8 on a hovered item
Use hotkey (menu closed)LEFT SHIFT + 1-8

Controller Support ​

The menu works seamlessly with controllers. Configure controller keys in the keys config:

lua
keys = {
    toggle = 0x80F28E95,    -- Controller L arrow
    left = 0xC0651D40,      -- R stick up
    right = 0x8ED92E16,     -- R stick down
    select = 0xCEFD9220,    -- E
    back = 0x156F7119,      -- BACKSPACE
},

The wheel has three built-in modes, switchable with the R key:

  • Main Menu - Your configured menu items
  • Favorites - Up to 8 favorited items with assigned slots
  • History - Recently used items, automatically tracked

Configure mode names and persistence in config:

lua
modes = {
    main = {
        name = "Main menu",
        icon = { dict = "toasts_mp_generic", name = "toast_mp_standalone_sp" }
    },
    favorites = {
        name = "Favorites",
        icon = { dict = "generic_textures", name = "star" },
        persistent = true -- Save to local db (false = session only)
    },
    history = {
        name = "History",
        icon = { dict = "toasts_mp_generic", name = "mp_roles_collector_tier" },
        persistent = false
    }
}

Favorites & Hotkey Slots ​

Assigning Items to Slots ​

  1. Open the wheel menu and hover over an item
  2. Hold a number key (1-8) until the progress bar fills
  3. The item is now assigned to that slot

Using Hotkeys ​

With the menu closed, press LEFT SHIFT + Number (1-8) to instantly execute the assigned item.

Favorites Mode ​

Switch to Favorites mode (R key) to see all assigned slots. Slot numbers are always visible. Use V (hold) to remove an item from favorites.

Adding Menu Items ​

Items are defined in shared/menu.lua:

lua
Menu.items = {
    {
        name = "item_unique_id",
        label = "Item Name",
        icon = {
            texture_dict = "texture_dictionary",
            texture_name = "texture_name"
        },
        color = { r = 255, g = 255, b = 255, a = 255 },
        action = function()
            -- Your code here
        end
    },

    -- Item with submenu
    {
        name = "submenu_id",
        label = "Submenu Name",
        icon = { texture_dict = "...", texture_name = "..." },
        color = { r = 255, g = 255, b = 255, a = 255 },
        items = {
            {
                name = "sub_item_1",
                label = "Submenu Item 1",
                icon = { texture_dict = "...", texture_name = "..." },
                color = { r = 255, g = 255, b = 255, a = 255 },
                action = function()
                    -- Action for submenu item
                end
            },
        }
    }
}

You can nest menus as deep as you want: menu > menu > menu > menu ...etc

Example With Nested Menus ​

lua
Menu.items = {
    {
        name = "clothing_menu",
        label = "Clothes Menu",
        icon = { texture_dict = "inventory_items_mp", texture_name = "clothing_generic_m_sweater" },
        color = { r = 255, g = 255, b = 255, a = 255 },
        items = {
            {
                name = "hat_menu",
                label = "Hat",
                icon = { texture_dict = "inventory_items_mp", texture_name = "clothing_generic_m_sweater" },
                color = { r = 255, g = 255, b = 255, a = 255 },
                items = {
                    -- Hat submenu items
                }
            },
        }
    },

    {
        name = "wagon_menu",
        label = "Call My Wagon",
        icon = { texture_dict = "inventory_items_mp", texture_name = "generic_coach" },
        color = { r = 255, g = 255, b = 255, a = 255 },
        items = {
            {
                name = "hunting_wagon",
                label = "Hunting Wagon",
                icon = { texture_dict = "inventory_items_mp", texture_name = "generic_coach" },
                color = { r = 255, g = 255, b = 255, a = 255 },
                action = function() print('Calling hunting wagon..') end
            },
            {
                name = "delivery_wagon",
                label = "Delivery Wagon",
                icon = { texture_dict = "inventory_items_mp", texture_name = "generic_coach" },
                color = { r = 255, g = 255, b = 255, a = 255 },
                action = function() print('Calling delivery wagon..') end
            }
        }
    }
}

Filtering System ​

Config.filter runs synchronously whenever the menu needs an item’s state (it must return immediately; do not Wait or block inside the filter). It receives the item name (as defined in shared/menu.lua) and may use any logic: job, admin flags, game state, exports, etc.

If data arrives from the server later, store it in a client variable and read it in the filter; the next frame will pick up the new value. For the gap before data is loaded, return values that match how you want the menu to behave (for example, allow all items until the first sync, or the oppositeβ€”your choice).

filterMode (global default) ​

lua
filterMode = 'disable', -- 'disable' or 'hide'

When you return only true or false, the second return is missing and the resource uses filterMode as the per-item mode for that decision:

filterModeEffect when the filter disallows the item
'disable'Item stays visible with a lock; cannot run action or open a submenu, but the wedge is still there.
'hide'Item is not shown as a normal entry; it becomes a ghost wedge (faded background, no icon).

For explicit per-item behavior, return a second value and ignore filterMode for that branch (see below).

Per-item return values ​

Config.filter should return one or two values:

  1. First return: true = item is allowed, false = item is not allowed (interpret with second return or filterMode).
  2. Second return (optional): 'disable' or 'hide' to override filterMode for that itemName.
ReturnsResult
return trueItem enabled, normal.
return false, 'disable'Disabled (locked): visible, lock icon, no action / no submenu.
return false, 'hide'Hidden (ghost): not interactive; shows as a faded β€œempty” style wedge.

If you return only one value, filterMode is used as the mode for a false result. If you return two values, the second overrides filterMode for that item.

filterHideItemOrder ​

lua
filterHideItemOrder = 'compact', -- 'in_place' or 'compact'

This controls order on the wheel for items that resolve to ghost ('hide') in Main mode (root list and every submenu, while the mode is Main).

ValueBehavior
'compact'(default)All non-ghost entries (visible + disabled/locked) first, in file order, then all ghost entries at the end of that list, in their original order among hiddens.
'in_place'Ghost wedges stay in the same order as in menu.lua (interleaved with visible items).

Example ​

lua
Config = {
    filterMode = 'disable', -- default when you only return true/false (no 2nd value)
    filterHideItemOrder = 'in_place', -- or 'compact' for Main mode only (see above)

    filter = function(itemName)
        if itemName == "delivery_wagon" then
            return false, 'disable'  -- show locked, no action
        end

        if itemName == "admin_panel" and not IsPlayerAdmin() then
            return false, 'hide'     -- ghost wedge (or at end of list if compact)
        end

        return true
    end,
}

You can override the global filterMode per item by always returning a second parameter where needed, as in the example.

Interaction Modes ​

lua
Config = {
    showMode = 'hold', -- 'toggle' or 'hold'
}
  • toggle - Press the key once to open, press again to close
  • hold - Hold the key to keep open, release to close

Exports ​

lua
-- Enable the menu
exports.bln_wheel:EnableMenu()

-- Disable the menu
exports.bln_wheel:DisableMenu()

-- Check if the menu is enabled
local isEnabled = exports.bln_wheel:IsMenuEnabled()

-- Check if the menu is currently visible
local isVisible = exports.bln_wheel:IsMenuVisible()

-- Force close the menu
exports.bln_wheel:CloseMenu()

Custom Icons ​

To use custom icons instead of game native icons, stream your own textures. See the custom textures tutorial for details.

Notification Settings ​

Configure notification messages and placement in shared/config.lua:

lua
notification = {
    placement = "middle-right",
    help_placement = "middle-right",
    messages = {
        ['added_to_favorites'] = "Added to favorites: ~#ffcc00~%s~e~",
        ['removed_from_favorites'] = "Removed from favorites: ~#ffcc00~%s~e~",
        ['favorites_limit_reached'] = "Favorites limit reached!",
        ['assigned_to_slot'] = "Assigned ~#ffcc00~%s~e~ to slot %d",
        ['slot_replaced'] = "Replaced slot %d with ~#ffcc00~%s~e~",
        ['slot_empty'] = "Favorite slot %d is empty",
        ['executed_from_slot'] = "~#ffcc00~%s~e~",
        ['cannot_assign'] = "Cannot assign this item to favorites",
        ['cannot_assign_menu'] = "Navigate into this menu and select an item to assign",
        ['help_title'] = "~#ffcc00~Wheel Menu~e~",
        ['help'] = "Hold ~key:1~ - ~key:8~ to assign item to a hotkey slot. Use ~key:SHIFT~ + number outside menu to quick use.",
    }
}

Support ​

Need help? Join our Discord server for support and updates!

  • Discord: Join Here
  • Live support and community help
  • Regular updates and improvements