Skip to content
swkeep edited this page Aug 13, 2025 · 3 revisions

A standalone raycast-based interaction menu for FiveM, designed to enhance your interaction with the environment on your FiveM server.

The primary goal is not to replace target scripts; instead, it can be used simultaneously to enhance script interactions within the FiveM. Nonetheless, the main factor is not just features it's because this script uses sprites and DUI, making it more demanding on resources compared to NUI-based scripts.

Preview

Youtube

Usage

create()

To create all types of interactions we're just going to use create() (or Create()) to generate the interactions.

  • We achieve this by using a type field in each interaction menu.
  • The nice thing is, script will automatically detect the type and there's no need for us to type it.
exports['interactionMenu']:create ( { Properties } )
exports['interactionMenu']:Create ( { Properties } )

List Of Properties (create)

Property Type Description
id String A unique identifier assigned to the menu. (If not provided, script will assign a random id)
type String Type of interaction (auto assign)
theme String Theme name (default, red, green, yellow)
glow Boolean Whether the menu has a glowing border around it
suppressGlobals Boolean Control the visibility of other menus, ignoring other menus
static Boolean If the entity is static and its position remains unchanged, using this option can have a better performance
zone Vector3 Defines the zone-based interaction
position Vector3 Defines the position-based interaction
rotation Vector3 Defines the rotation of interaction menu (3d) (works while either position or zone present)
entity String Defines an interaction based on a specific entity
model String Defines an interaction on all entities of the same model
vehicle String Used in interactions within vehicles
bone String Defines an interactions within a vehicle parts (e.g. wheels)
maxDistance Table The maximum distance at which the menu is accessible
extra Table Additional properties for the menu
indicator Table Menu indicator
options Table List of options available in the menu

Automatic dark theme

The interaction menu features an automatic dark theme selection based on the time of day.

  • This is implemented to address visibility issues with the default theme, especially when there is too much light.
Light Theme

Light Theme

Dark Theme

Dark Theme

triggers

By using events or actions we can trigger part of our code when player interacted with and specifid option in our interaction menu.

action
Property Type Description
type String Type of action. Possible values: sync,async
func Function The action function
  • sync actions will put the interaction menu into loading/exuting mode and won't be usable till out action is finished.
-- other options
{
    label = 'Drink',
    action = {
        type = 'sync',
        func = function(entity, distance, coords, name, bone) 
            print(entity, distance, coords, name, bone)
        end
    }
}
-- other options
event
Property Type Description
type String Type of action. Possible values: client,server
name String Event name
payload Any (except function) Payload
-- other options
{
    label = 'Drink',
    event = {
        type = 'client',
        name = 'test:event:drink',
        payload = 'something'
    }
}
-- other options
AddEventHandler('test:event:drink', function(payload, data)
    print(payload) -- 'something'
    Util.print_table(data) 
    -- data => {
    --     entity,
    --     distance,
    --     coords,
    --     name,
    --     bone 
    -- }
end)
zone

So, imagine you're in a game world, right? Now, think of a "zone" as an invisible area within that world. This zone is there to define certain rules or trigger certain actions when players or objects enter or leave it.

Property Type Description
type String Type of zone. Possible values: boxZone,entityZone, circleZone, polyZone, comboZone
name String The name of the zone
position Object The position of the zone
heading Number The heading of the zone
width Number The width of the zone
length Number The length of the zone.
debugPoly Boolean Whether to display debug zone
minZ Number The minimum Z coordinate of the zone
maxZ Number The maximum Z coordinate of the zone

box zone + rotation = 3d

exports['interactionMenu']:Create {
    id = 'ZoneTest',
    rotation = vector3(-40, 0, 240),
    position = vector4(-1965.7, 3188.65, 32.81, 58.08),
    scale = 1,
    zone = {
        type = 'boxZone',
        name = "onZoneTest",
        position = p,
        heading = p.w,
        width = 4.0,
        length = 6.0,
        debugPoly = true,
        minZ = p.z - 1,
        maxZ = p.z + 1,
    },
    options = { ... }
}
static

The static menus won't update the entities's positions on runtime, even though this will offer better performance, choose it carefully and make sure those entities won't move.

static = false (Default)

static = true

glow

You can choose to make the menu have a glowing border.

Glow

glow = true

exports['interactionMenu']:Create {
    ...
    glow = true -- // [!code focus]
    ...
}

Indicator glow

Indicators can have a glow effect to.

Glow

glow = true

exports['interactionMenu']:Create {
    ...
    indicator = {
        prompt = 'Press Enter',
        glow = true -- // [!code focus]
    },
    ...
}
suppressGlobals

You have the option to create a unique menu on the entity and remove all global menus.

suppressGlobals

suppressGlobals = false

suppressGlobals

suppressGlobals = true

indicator

Menus can have custom indicators with custom key triggers that players must press to initiate actions and events.

  • The default trigger is E
Property Type Description
prompt String Prompt string
glow Boolean Glow effect
keyPress keyPress Controls used to trigger events and actions
keyPress

Check these two links for more information Controls Reference, Natives Reference

Property Type Description
padIndex String The control system instance to use
control Table The control ID to check

Example

exports['interactionMenu']:Create {
    ...
    indicator = {
        prompt   = 'Custom indicator',
        keyPress = {
            padIndex = 0,
            control = 38 -- press E
        }
    },
    ...
}
extra
Property Type Description
onSeen String Triggers the onSeen function upon seeing the menu
onExit Table Triggers the onExit function upon exiting the menu
onTrigger Table Triggers the onTrigger function upon triggering the triggers
job Table Job check (currently not working)

Example

exports['interactionMenu']:Create {
    ...
    extra = {
        onSeen = function(data)
            print('onSeen')
        end,
        onExit = function(data)
            print('onExit')
        end,
        onTrigger = function(data)
            print('onTrigger')
        end
    },
    ...
}

Create an interaction on a specific position.

FOV

There's an optimization layer with a field of view function placed in script, meaning script is going to show up only when we are directly looking at it.

local controlPoint = vector4(-1996.67, 3155.48, 31.81, 95.00) -- vector 3 is enough

local menuId = exports['interactionMenu']:Create {
    id = 'uniqueId',
    type = 'position', -- technically, we don't need it 
    position = controlPoint,
    maxDistance = 2.0,
    options = { ... } -- Replace this with your actual options
}

print(menuId) -- uniqueId
option

Here we describe each property that you can use in each option to create interactions on each menu.

Property Type Description
label String Label
icon String Optional icon (fontawesome)
canInteract Function reutrn false to hide the option
action Table Action triggered after the option is selected by the player
event Table Event triggered after the option is selected by the player
video Table Video property
style Table Custom style
progress Table Show a progress bar
bind Table Bind the value of progress to a function
picture Table Show a picture
dynamic Boolean Set the option as dynamic (value can be updated in runtime)

Let's create a simple menu as an example and continue working on that.

Here we'll spawn a new entity and add an interaction to it.

Globals

The first option (Debug) is a test/debug option, which I'll discuss in the globals section.

Example

local controlPoint = vector4(-1996.67, 3155.48, 31.81, 95.00)
local ent = Util.spawnObject(`prop_watercooler`, controlPoint)

exports['interactionMenu']:Create {
    entity = ent,
    maxDistance = 2.0,
    options = {
        {
            label = 'Drink',
            event = {
                type = 'client',
                name = 'test:event:drink',
                payload = 'something'
            }
        }
    }
}

By using actions:

Actions

The type can be either sync or async. To use the sync function, follow this format:

  • Please note that this format is subject to change.
  • Interactions have to wait until the execution of functions is finished, which is not ideal as it uses system resources.
action = {
    type = 'sync',
    name = function(entity, distance, coords, name, bone) 
        print(entity, distance, coords, name, bone)
    end
}

:::


```lua
local controlPoint = vector4(-1996.67, 3155.48, 31.81, 95.00)
local ent = Util.spawnObject(`prop_watercooler`, controlPoint)

exports['interactionMenu']:Create {
    entity = ent,
    maxDistance = 2.0,
    options = {
        {
            label = 'Drink',
            action = {
                type = 'sync',
                name = function(entity, distance, coords, name, bone) 
                    print(entity, distance, coords, name, bone)
                end
            }
        }
    }
}
canInteract

A function which you can use to hide options.

Example

-- other options
{
    label = 'Drink',
    style = {
        color = {
            label = 'rgb(0, 255, 0)',
        }   
    },
    event = {
        type = 'client',
        name = 'test:event:drink',
        payload = 'something'
    },
    canInteract = function(entity, distance, coords, name, bone)
        return true -- show option
    end
}
-- other options
style

These properties are style properties we can use on each individual option.

Property Type Description
color.background String Background color
color.label String Label color
color.labelSelected String Selected label color
color.backgroundSelected String Background color when selected
text.labelFontSize String Font size for labels

Example

-- other options
{
    label = 'Drink',
    style = {
        color = {
            label = 'rgb(0, 255, 0)',
        }   
    },
    event = {
        type = 'client',
        name = 'test:event:drink',
        payload = 'something'
    }
}
-- other options
video

Each option can serve a role more than triggering actions and events. Here, we want to just display a video to players when they see the menu.

Property Type Description
url String URL of the video
opacity Number Opacity of the video
currentTime Number Current playback time
autoplay Boolean Autoplay the video
loop Boolean Loop the video
progress Boolean Show progress bar
percent Boolean Show percentage progress
timecycle Boolean Enable time cycle
volume Number Volume level

Example

-- other options
{
    video = {
        url = 'http://127.0.0.1:8080/TEST VIDEO.mp4',
        volume = 0,
        currentTime = 100,
        progress = true,
        autoplay = true,
        loop = true
    }
},
-- other options

We can't use YouTube and other streaming services. Only videos hosted on servers with streaming enabled. You can host them on your game server or use FiveM to load them within your scripts and display videos locally.

picture

Same as the previous option where we could show videos, we can also display images. Here are the properties we can use:

Property Type Description
url String URL of the picture
opacity Number Opacity of the picture
width Number Width of the picture
height Number Height of the picture
border BorderType Type of border around picture (dash, solid, double, none)

Example

-- other options
{
    picture = {
        url = 'http://127.0.0.1:8080/00221-1775208258.png'
    }
},
-- other options
progress

You can display a progress bar within the menu to represent values between 0-100. Also, you have the option to bind a function and update the value from there.

  • The progress value is updated whenever bound value changes.
Property Type Description
type String Type of progress
value Number Value of the progress
percent Boolean Show percentage progress

Example

-- other options
{
    label = "Health",
    progress = {
        type = "info",
        value = 0,
        percent = true
    },
    bind = {
        func = function(entity, distance, coords, name, bone)
            return GetEntityHealth(entity) / 10
        end
    }
}, 
-- other options

createGlobal()

Global Interactions, Here, instead of using create(), we use createGlobal() (or CreateGlobal()) to create global interactions.

  • Global interactions can be applied to various types such as peds, player, entities, bones, and vehicles.
exports['interactionMenu']:createGlobal { Properties }
exports['interactionMenu']:CreateGlobal { Properties }

Properties are essentially the same properties we have in create().

::: code-group

exports['interactionMenu']:createGlobal {
    type = 'entities',
    offset = vec3(0, 0, 0),
    maxDistance = 1.0,
    options = {
        {
            label = '[Debug] On All Entities',
            icon = 'fa fa-bug',
            action = {
                type = 'sync',
                func = function(entity, distance, coords, name, bone)
                end
            }
        }
    }
}
exports['interactionMenu']:createGlobal {
    type = 'peds',
    offset = vec3(0, 0, 0),
    maxDistance = 1.0,
    options = {
        {
            label = '[Debug] On All Peds',
            icon = 'fa fa-person',
            action = {
                type = 'sync',
                func = function(entity, distance, coords, name, bone)
                end
            }
        }
    }
}
exports['interactionMenu']:createGlobal {
    type = 'vehicles',
    offset = vec3(0, 0, 0),
    maxDistance = 1.0,
    options = {
        {
            label = '[Debug] On All Vehicles',
            icon = 'fa fa-car',
            action = {
                type = 'sync',
                func = function(entity, distance, coords, name, bone)
                end
            }
        }
    }
}
exports['interactionMenu']:createGlobal {
    type = 'players',
    offset = vec3(0, 0, 0),
    maxDistance = 1.0,
    options = {
        {
            label = '[Debug] On All Players',
            icon = 'fa fa-person',
            action = {
                type = 'sync',
                func = function(entity, distance, coords, name, bone)
                end
            }
        }
    }
}
exports['interactionMenu']:createGlobal {
    type = 'bones',
    bone = 'platelight',
    offset = vec3(0, 0, 0),
    maxDistance = 1.0,
    options = {
        {
            label = '[Debug] On All plates',
            icon = 'fa fa-rectangle-ad',
            action = {
                type = 'sync',
                func = function(entity, distance, coords, name, bone)
                end
            }
        }
    }
}

:::

set()

With set() or setValue() function, you'll be able to adjust various properties of a menu at runtime.

For example, you can hide a menu, change its position (position-based menus), update labels, or modify progress value.

Property Type Description
menuId String The ID of the menu to be modified
type String The type of property to be modified ('hide', 'position', 'label', or 'progress')
option Number (Optional) The index of the option within the menu to be modified
value any The new value to be set for the specified property
local id = exports['interactionMenu']:Create {
    entity = ent2,
    offset = vec3(0, 0, 1),
    options = {
        {
            label = "Above Menu",
            icon = "fas fa-heartbeat",
        }
    }
}

if this is our menu we can use its id and hide it by updating hide peropety of the menu.

exports['interactionMenu']:set {
    menuId = id,
    type = 'hide',
    value = true
}

However, if we only want to hide a single option, we can provide the option, which will hide that specific option for us.

exports['interactionMenu']:set {
    menuId = id,
    option = 2,
    type = 'hide',
    value = true
}

We can also update the position of the menu, label, and progress value of options.

:::tip Dynamic

To update the progress or label value, option must be a dynamic.

{
    label = "Health",
    icon = "fas fa-heartbeat",
    dynamic = true, -- // [!code focus]
    progress = {
        type = "error",
        value = 50,
        percent = true
    }
},

:::

For example, updating the label:

also, we can update the position of position-based interactions too

exports['interactionMenu']:set {
    menuId = id,
    type = 'position',
    value = vector4(-1981.69, 3188.51, 32.81, 111.91)
}

remove()

After adding numerous menus, it's always beneficial to remove some of those. In such cases, we can utilize the remove function to delete an interaction by using its id.

exports['interactionMenu']:remove(id)
Property Type Description
id String The ID of the menu to be modified

Support

If you need any help or have any questions about our products, please join our discord channel: https://discord.gg/ccMArCwrPV