addPoint, keep the returned id if you ever want to remove it, and the layer handles the rest - the reveal stages, focus, and input all come for free. Everything a resource registers is cleaned up automatically when that resource stops.
Points are indexed in a spatial grid, and the frame loop only ever looks at the player’s neighborhood - so thousands of registered points cost nothing at idle. Register your whole map up front; there’s no need to create and destroy points as players move around.
Quick Start
8.0m, the label grows out of the grain at 4.5m, and within 2.4m the stack is live. The defaults come from Config.Stages and can be overridden per point with stages - see How It Works for the full attention model.
Functions
addPoint
addPoint
Register a static interaction point.Parameters:
data(table) - Point configuration (see Point Options)
id(number) - The point’s anchor id, forremove- ornilif the data was invalid (the reason is printed to the client console)
remove
remove
Remove an anchor by id. Parameters:
removePoint is an alias - both accept the id returned by any add* export, whatever its kind.id(number) - The id returned at registration
Manual removal is only needed for points that stop making sense mid-session. Everything your resource registered is removed automatically when it stops or restarts.
Configuration
Point Options
vector3
required
World position of the point. A
vector4 or a plain { x, y, z } table (JSON, database rows) is accepted toostring
Header line of the stack
Optional - without one (or when it just repeats the first option’s label) the stack renders headerless: the header line is the first option. Ideal for single-action points.
string
FontAwesome solid icon name for the anchor (e.g.
'credit-card') - omit for the default dottable
required
Array of one or more option tables (see Option Fields)
table
Per-point overrides of the reveal distances, in meters:
{ grain = 8.0, name = 4.5, reach = 2.4 }Any key you omit keeps its Config.Stages defaultstring
default:"smart"
How the stack opens once the player is in reachAvailable options:
'smart', 'auto', 'manual''smart' unfolds single-option points on their own and holds multi-option points as a pill until the confirm key opens the list; 'auto' always unfolds; 'manual' always waits for the confirm key. The default comes from Config.ExpandModestring
default:"ambient"
What renders before the point is focusedAvailable options:
'ambient', 'focus''ambient' marks the point with a grain of light from the grain stage onward; 'focus' renders nothing until attention lands on it. Points default to 'ambient' (Config.Reveal.point)boolean
default:"false"
Draw the point’s reach sphere in-world, at any distance - useful while placing coordinates
boolean
Hidden until the interact control is held - see passive mode. Defaults to
Config.Passive, or true when your resource is listed in Config.PassiveResourcesboolean
Whether the point stays live while the player sits in a vehicle. Unset, it follows
Config.InVehicle.points (true)Option Fields
Each entry inoptions describes one row of the stack:
string
required
Row label
string
FontAwesome solid icon name (e.g.
'money-bill')string
Keyboard key this option binds to, by name (
'E', 'T', '5', 'F2', 'SPACE', …) - pressing it while the stack is open activates the option directlyOmit to leave the option unbound: the confirm key (
E by default) activates it while it’s the highlighted row, and the cursor (hold Left Alt and click - then hover, click) reaches it anywhere in the list. Binding a key name that doesn’t exist fails the registration with a console error.number
Milliseconds the key must be held - a ring fills while held and the option fires when it completes; releasing early cancels. Omit or
0 for instant activationboolean
default:"false"
Keep the list open after selecting this option (repeatable actions) -
'manual' lists fold back to the pill after a selection by defaultstring | string[] | table
Job/gang gate:
'police', { 'police', 'sheriff' } (any of), or { police = 2 } (any of, at that minimum grade)Matches whatever your framework reports as the player’s groups - jobs and gangs alike. Custom setups can adapt the check in bridge/client.luastring | string[] | table
Inventory gate:
'lockpick', { 'lockpick', 'screwdriver' } (all of), or { lockpick = 2 } (required counts)Supported inventories are detected automatically; custom setups can adapt the check in bridge/client.luafunction
Predicate deciding whether the row is currently visible - return Evaluated off the frame path on a dedicated thread every
true to show it:50ms while the point is focused (and about 5x/s while merely nearby) - a slow predicate only delays its own rows, never the element or input. It is not re-run at activationfunction
Handler called when the option activates, with a single payload table:Handlers dispatch from their own thread, so it’s safe to
Wait, open UIs, or await server callbacks insidestring
Client event triggered on activation with the same payload table as
onSelectstring
Server event triggered on activation with
{ id, index, args, netId, coords } (netId is nil for points)any
Passed through to
canInteract and every handleronSelect, event, and serverEvent are not exclusive - an option may set any combination, and all of them fire.Gated Options and Visibility
Rows gated bygroups, items, or canInteract simply don’t render for players who fail the gate - the stack shows only what the player can actually use. If every option on a point is gated away, the point disappears entirely: no grain, no focus, nothing to see.
