NUI setup

This guide will help you to set up the emote wheel in the NUI (not the emotes itself, see for this).

This might be new for you: Because to set up the emote wheel it would be helpful if you know something about the JavaScript programming language. But don't worry, even if JavaScript doesn't mean anything to you. We have collected some examples. You can copy the examples and adapt, duplicate and extend them as you like.

Why (the fuck) JavaScript?

In short:

Because we think it's better that way ;)

In more detail:

NUI stands for Network User Interface and is a way to display a user interface in the game. This is done via a web browser as overlay in the game. This web browser is called CEF (Chromium Embedded Framework) - or in simple words some version of Google Chrome.

Anyway, that's why the NUI is basically based on web pages. Web pages are declared in HTML (Hyper Text Markup Language), beautified by CSS (Cascading Style Sheets) and brought to life by JavaScript. That's where you come in. The emote wheel can be very complex even bigger it grows. This will be too complicated via Lua configuration file. Transferring the emote wheel configuration from the client to the NUI can also be very time-consuming. So we have decided to use directly a JavaScript file for this.

Why (the fuck) *.demo.js files?

In short:

To prevent overwriting your config files each time the resource is updated.


No one is safe from mistakes. So sometimes during "writing" (coding) the configuration, something may go wrong. In this case you can use the Developer Tools of the browser to debug the NUI. Open the REDM console via F8 and choose Tools > NUI > Open DevTools from the context menu. If the game is running, you will see the Developer Tools of the NUI. There you can see the Console tab. The Console tab is the place where you can see the errors and warnings of the NUI.

Create config.js

If you set up the resource the first time there is no config.js file. Go into the folder html_nss_emotes and copy config.demo.js to config.js. Now you can start with the configuration.

Why is there a config.demo.js file?

This may seem unusual to you. But to prevent that the configuration is accidentally overwritten during updates, there is a demo configuration. The demo configuration may contain new features during updates and serves as a blueprint.

Basic config.js format

The config.js file is a JavaScript file. In detail, it is a JavaScript module. Modules can be imported by other modules (which the emote wheel module do). The following is the basic structure of the config.js file:

import {NssEmotesConfig} from "./Classes/NssEmotesConfig.js";

const config = new NssEmotesConfig();


export {config}

Important: The lines before // DO NOT TOUCH THE LINES ABOVE and after // DO NOT TOUCH THE LINES BELOW are mandatory and must not be touched.

// DO YOUR CONFIGURATION HERE is the place where you can start your configuration. You can add as many lines as you want and as many lines as you need.

What is the config object?

config is an object (in detail it is an instance of the class NssEmotesConfig) that contains all the configuration for the NUI of the emote wheel. This object has so-called methods that can be called to configure the emote wheel. The methods are described in the following sections.

What are the other *.demo.js files for?

The other *.demo.js files are demo files with prepared configurations like emotes or walk styles. You will find more information about this in the config.demo.js (or config.js) file.


Wheel buttons can have icons. These icons must be placed in the html_nss_emotes/icons folder.

We do not allow the use of icons from external resources. This is to prevent your players from having to download external resources (which can be a security risk). If the icons are stored locally in the resource the loading times are faster.

We recommend using the SVG format for the icons. This format is very small and can be scaled without loss of quality. It has also an alpha channel (transparency) and can be colored with CSS. Additionally, PNG files can be used, too.


Not implemented currently.

Key bindings

The emote wheel can be opened with a key binding but this is part of the configuration in the config.lua file.

With the following code you can define all keys for the NUI emote wheel:

config.defineCloseKeys('X', 'Escape', 'Backspace'); // You can define as many keys as you want
config.defineWheelBackKey('rmb', 'mouse4', 'ArrowUp'); // You can combine keyboard keys and mouse buttons
config.defineDialogCloseKeys('x', 'Backspace');
config.defineDialogBackKeys('rmb', 'mouse4', 'Escape');

config.defineCancelAnimCommand('actstop'); // The command that is executed when the cancel animation key is pressed

See for available keyboard keys.

Available mouse buttons are:

  • lmb (left mouse button)

  • scroll (mouse wheel)

  • rmb (right mouse button)

  • mouse4 (mouse button 4, in most cases the back button on the mouse)


  • The key bindings are case-insensitive. So x is the same as X.

  • Numbers are not allowed as key bindings because 0-9 are used for the hotbar buttons.

UI Options

The emote wheel has some options that can be configured. The following code shows the default values of the options:

config.defineDefaultSfxVolumeInPercent(100); // Value between 0 and 100, steps in 10
config.defineDefaultBgFx('WheelHUDIn'); // See Config.BackgroundFxList in config.lua for available values


The emote wheel can be customized with colors. The following code set up the default colors of the emote wheel:

// Optional: Emote wheel colors
config.defineDefaultWheelBgColor('#000000'); // Black
config.defineDefaultWheelHoverColor('#990000'); // Dark red
config.defineDefaultWheelClickColor('#ffffff'); // White

// Optional: Hotbar colors
config.defineDefaultHotbarBgColor('#000000'); // Black
config.defineDefaultHotbarHoverColor('#990000'); // Dark red
config.defineDefaultHotbarClickColor('#ffffff'); // White

The colors are defined as CSS hex colors.

Important: Custom colors of emote wheel buttons will not be applied to the hotbar buttons on assignment.

Root wheel

The root wheel is the "highest" wheel (like a folder) that is displayed when the NUI is opened. The root wheel has to be created first and can be customized with the following code:

// Creates the root wheel saved in the variable "root_wheel". You can rename the variable as you want.
const root_wheel = config.createRootWheel();

// Sets the label of the root wheel OR ...

// ..sets an image for the root wheel (image hides label).
root_wheel.setImage('your-logo-name.png'); // The image must be placed in the "html_nss_emotes/logos" folder. If the folder does not exist, create it.

// The following settings are each optional if you want to defer them to the default settings
root_wheel.setBgColor('#000099'); // Dark blue
root_wheel.setHoverColor('#009900'); // Dark green
root_wheel.setClickColor('#00ffff'); // Cyan

config.createRootWheel() creates a new object that represents the configuration of the root wheel. This object has methods that can be called to configure the root wheel. In the example above we save the object in the variable root_wheel which we can use later to configure the root wheel settings or add buttons to the root wheel.

Tip for wheel images via setImage():

  • Use high resolution images.

  • Use a transparent background.

  • Use a square image (e.g. 512x512 pixels or higher) but a rounded logo!

Pro-tip: Make it short via chaining!

Chaining is possible for almost all methods.

const root_wheel = config.createRootWheel().setLabel('Home').setBgColor('#000099').setHoverColor('#009900').setClickColor('#00ffff'); // Don't forget the semicolon!


const root_wheel = config.createRootWheel()
    .setClickColor('#00ffff'); // Don't forget the semicolon!

It's up to you which style you prefer.

Wheel Buttons

Use the root_wheel (or other wheel) object to add buttons to it:

// Creates a button object saved in the variable "drunken_walk_style_btn". You can rename the variable as you want.
const drunken_walk_style_btn = root_wheel.addButton();

// The following settings are each required.

// Choose only one of the following settings each button! You see here all available settings for example.
drunken_walk_style_btn.setCommand('drunken_walk_style'); // Command supports arguments too. Example: 'drunken_walk_style arg1'

// At least the "icon" or "label" is required. You can set both if you wish.
// If a "inventory item" is used then "icon" and "label" are optional. The "icon" overrides the "inventory item" icon.
drunken_walk_style_btn.setIcon('drunken_walk_style.png'); // See chapter "Icons" for more information. Overrides the "inventory item" icon.

// You can set directly a label or use the related translation key from your language file.
drunken_walk_style_btn.setLabel('Drunken walk style'); /* OR */ drunken_walk_style_btn.setTranslationKey('WalkStyleDrunk')

// The following settings are each optional if you want to defer them to the default settings

// Colors (overrides the colors of the root wheel)
drunken_walk_style_btn.setBgColor('#000099'); // Dark blue
drunken_walk_style_btn.setHoverColor('#009900'); // Dark green
drunken_walk_style_btn.setClickColor('#00ffff'); // Cyan

// Keeps the emote wheel open after the button was clicked (works only in wheel not in hotbar or search)

// Restrict usage to chars:
// Only the char ids 207 and 210 can use that button
// Restrictions will be inherited to sub wheels recursively. So you have to set the restrictions only once.
// New since 1.2.0

// Restrict usage to groups:
// Only the groups admin and moderator can use that button
// Restrictions will be inherited to sub wheels recursively. So you have to set the restrictions only once.
// New since 1.2.0

// Restrict usage to jobs:
// Only the jobs police and ambulance can use that button
// Restrictions will be inherited to sub wheels recursively. So you have to set the restrictions only once.
// New since 1.2.0
drunken_walk_style_btn.restrictToJob('police'); // All job grades of police can use that button
drunken_walk_style_btn.restrictToJob('ambulance', 2); // Only the job grade 2 and higher of ambulance can use that button

Here an example with chaining and more buttons (without custom colors):

root_wheel.addButton().setLabel('Drunken walk style').setCommand('drunken_walk_style').setIcon('drunken_walk_style.png').restrictToGroup('admin');
root_wheel.addButton().setLabel('Hurt walk style').setCommand('hurt_walk_style').setIcon('hurt_walk_style.png');
root_wheel.addButton().setLabel('Injured walk style').setCommand('injured_walk_style').setIcon('injured_walk_style.png').restrictToChar('207').restrictToChar('210');
root_wheel.addButton().setLabel('Injured walk style 2').setCommand('injured_walk_style_2').setIcon('injured_walk_style_2.png');
root_wheel.addButton().setLabel('Happy walk style').setCommand('happy_walk_style').setIcon('happy_walk_style_3.png').restrictToJob('sheriff', 2);

This is much shorter than the previous example. It is not necessary to save the buttons in variables because they are not needed later.

Button types

  • Command buttons, e.g. setCommand('drunken_walk_style');, can be used to trigger chat/console commands including arguments.

  • Event buttons, e.g. setEventName('vorp_core:open_inventory');, can be used to trigger client events.

    • Tip: To call a server event create a client event that calls the server event.

  • Inventory item buttons, e.g. setInventoryItem('water');, can be used to trigger the usage of an inventory item.

    • Because we use Vorp a item related icon (existing in Vorp Inventory) will automatically be set to the button.

  • Folder buttons, see chapter "Sub wheels" for more information.

Sub wheels (folder buttons)

Sub wheels are wheels that are displayed when a folder button of a wheel is clicked. You can nest sub wheels as deep as you want. The folder buttons can have restrictions like the normal buttons. If a parent folder button has restrictions then the restrictions will be inherited to the sub wheels on creation.

// First create and configure the button first like described in the chapter "Wheel Buttons" but use the 
// method "addFolderButton()" instead of "addButton()".
// Important: Folder buttons have no command!
const walk_style_folder_btn = root_wheel.addFolderButton();
walk_style_folder_btn.setLabel('Walk styles'); // Required (as short as possible to fit in the button)
walk_style_folder_btn.setIcon('walk_style.png'); // Optional (see chapter "Icons" for more information)

// Second create the sub wheel and configure it like described in the chapter "Root wheel".
// The `getWheel()` is only available for folder buttons and returns a new the wheel object.
const walk_styles_wheel = walk_style_folder_btn.getWheel();


  • A folder button can only have one sub wheel (logical).

  • If the sub wheel has no label then the label of its folder button is used.

  • Each sub wheel can have its own colors. If the colors are not defined then the default colors will be used.

Last updated