Stand Lua API Documentation

Table of Contents

§ About Developing Stand Luas

Game Natives

This Stand Lua API that is described in this document is developed with the game's own scripting features in mind, which are at your fingertips with just a call to util.require_natives.

You can find a nice viewer for the game's native functions at nativedb.dotindustries.dev, which is powered by alloc8or's nativedb data.

Runtime Settings

We highly recommend using Stand > Lua Scripts > Settings > Presets > Developer and/or reviewing all the Lua runtime settings available to you, as they can help you write more polished and less buggy code.

Language

Stand uses Pluto which adds new features, improvements, and optimisations while being compatible with existing Lua code.

A language server and VS Code extension for Pluto is available at https://github.com/PlutoLang/pluto-language-server.

Bindings

Stand also provides Soup Lua Bindings.

External Resources

§ Types

Label

A string or the return value of lang.register.

CommandAny

Not an actual type, but the base for CommandRef and CommandUniqPtr, which both support the following operations:

  • .menu_name — shorthand for menu.get_menu_name/menu.set_menu_name
  • .command_names — shorthand for menu.get_command_names/menu.set_command_names
  • .help_text — shorthand for menu.get_help_text/menu.set_help_text
  • .name_for_config — shorthand for menu.get_name_for_config/menu.set_name_for_config
  • :equals(CommandAny) — returns a boolean that indicates if this CommandAny refers to the same command as another CommandAny instance
CommandRef

A reference to a command in Stand. Supports all of CommandAny's operations as well as:

  • :isValid() — shorthand for menu.is_ref_valid
  • :refByRelPath() — shorthand for menu.ref_by_rel_path
  • :delete() — shorthand for menu.delete
  • :detach() — shorthand for menu.detach
  • :attach(...) — shorthand for menu.attach
  • :attachAfter(...) — shorthand for menu.attach_after
  • :attachBefore(...) — shorthand for menu.attach_before
  • :focus() — shorthand for menu.focus
  • :isFocused() — shorthand for menu.is_focused
  • :getApplicablePlayers() — shorthand for menu.get_applicable_players
  • :getParent() — shorthand for menu.get_parent
  • :getType() — shorthand for menu.get_type
  • :getChildren() — shorthand for menu.get_children
  • :trigger() — shorthand for menu.trigger_command
  • :onTickInViewport(...) — shorthand for menu.on_tick_in_viewport
  • :onFocus(...) — shorthand for menu.on_focus
  • :onBlur(...) — shorthand for menu.on_blur
  • :removeHandler(...) — shorthand for menu.remove_handler
  • :getState() — shorthand for menu.get_state
  • :getDefaultState() — shorthand for menu.get_default_state
  • :applyDefaultState() — shorthand for menu.apply_default_state
  • :setListActionOptions(...) — shorthand for menu.set_list_action_options
  • :setActionSliderOptions(...) — shorthand for menu.set_action_slider_options
  • :setTemporary() — shorthand for menu.set_temporary
  • .visible — shorthand for menu.get_visible/menu.set_visible
  • .value — shorthand for menu.get_value/menu.set_value
  • .min_value — shorthand for menu.get_min_value/menu.set_min_value
  • .max_value — shorthand for menu.get_max_value/menu.set_max_value
  • .step_size — shorthand for menu.get_step_size/menu.set_step_size
  • :list(...) — shorthand for menu.list
  • :action(...) — shorthand for menu.action
  • :toggle(...) — shorthand for menu.toggle
  • :toggle_loop(...) — shorthand for menu.toggle_loop
  • :slider(...) — shorthand for menu.slider
  • :slider_float(...) — shorthand for menu.slider_float
  • :click_slider(...) — shorthand for menu.click_slider
  • :click_slider_float(...) — shorthand for menu.click_slider_float
  • :list_select(...) — shorthand for menu.list_select
  • :list_action(...) — shorthand for menu.list_action
  • :text_input(...) — shorthand for menu.text_input
  • :colour(...) — shorthand for menu.colour
  • :rainbow(...) — shorthand for menu.rainbow
  • :divider(...) — shorthand for menu.divider
  • :readonly(...) — shorthand for menu.readonly
  • :hyperlink(...) — shorthand for menu.hyperlink
  • :action_slider(...) — shorthand for menu.action_slider
  • :slider_text(...) — shorthand for menu.slider_text
CommandUniqPtr

Holds a detached command. Detached commands don't exist in the menu in any way, and are not usable via the command box.

Supports all of CommandAny's operations as well as:

  • :ref() — returns a CommandRef to the command
Vector3

A v3 instance or a table with x, y & z fields of type number.

Colour

A table with r, g, b & a fields of type number with values between 0.0 and 1.0.

Functions that take this as a parameter also support 4 floats instead of it, which is more performant.

§ Global Variables

SCRIPT_NAME

A string containing the name of your script (this excludes .lua).

SCRIPT_FILENAME

A string containing the name of your script file.

SCRIPT_RELPATH

A string containing the path to your script file from the Lua Scripts folder.

SCRIPT_MANUAL_START

A bool indicating if your script was started in direct response to a user action.

SCRIPT_SILENT_START

A bool indicating if a silent start of your script is desired.

SCRIPT_SILENT_STOP

A bool indicating if a silent stop of your script is desired.

SCRIPT_CAN_CONTINUE

A bool that remains true until your script is being stopped. You generally won't need to check against this as the runtime will handle the stop process, but in special situations like execute_in_os_thread, you might like to check against this to see if you want to continue with an expensive operation.

§ Menu Functions

CommandRef menu.my_root()

Returns a reference to the list that your script gets when it is started.

CommandRef menu.player_root(int player_id)

Returns a reference to the list that the given player owns.

CommandRef menu.shadow_root()

Using return value of this function to create a command produces a detached commmand (CommandUniqPtr) instead of a CommandRef.

CommandRef menu.ref_by_path(string path, ?int tree_version = nil)

Returns a reference to any command in Stand using a path such as Self>Immortality. Note that the path has to be in English (UK) and using the no-space greater-than separator.

Providing a tree version is optional but highly recommended for future-proofing. You can find this in any tree config file, such as your profile.

CommandRef menu.ref_by_rel_path(int base, string path)
CommandRef menu.ref_by_command_name(string command_name)
CommandRef|CommandUniqPtr menu.list(CommandRef parent, Label menu_name, table<any, string> command_names = {}, Label help_text = "", ?function on_click = nil, ?function on_back = nil, ?function on_active_list_update = nil)
CommandRef|CommandUniqPtr menu.action(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, function on_click, ?function on_command = nil, ?string syntax = nil, int perm = COMMANDPERM_USERONLY)

perm may be any of:

  • COMMANDPERM_FRIENDLY
  • COMMANDPERM_NEUTRAL
  • COMMANDPERM_SPAWN
  • COMMANDPERM_RUDE
  • COMMANDPERM_AGGRESSIVE
  • COMMANDPERM_TOXIC
  • COMMANDPERM_USERONLY

Your on_click function will be called with click_type and effective_issuer. The click type could be any of:

  • CLICK_MENU
  • CLICK_COMMAND
  • CLICK_HOTKEY
  • CLICK_BULK
  • CLICK_AUTO
  • CLICK_SCRIPTED
  • CLICK_WEB
  • CLICK_WEB_COMMAND
  • CLICK_CHAT_ALL
  • CLICK_CHAT_TEAM

And could match any or neither of these bitflags:

  • CLICK_FLAG_AUTO
  • CLICK_FLAG_CHAT
  • CLICK_FLAG_WEB

Your on_command function will be called with the provided arguments, click_type, and effective_issuer. If on_command is not provided, commands will be redirected to on_click.

CommandRef|CommandUniqPtr menu.toggle(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, function on_change, bool default_on = false)

Your on_change function will be called with on and click_type.

CommandRef|CommandUniqPtr menu.toggle_loop(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, function on_tick, ?function on_stop = nil)

Your on_tick function will be called every tick that the toggle is checked; you should not call util.yield in this context.

CommandRef|CommandUniqPtr menu.slider(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, int min_value, int max_value, int default_value, int step_size, function on_change)
CommandRef|CommandUniqPtr menu.slider_float(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, int min_value, int max_value, int default_value, int step_size, function on_change)

Your on_change function will be called with value, prev_value and click_type.

Note that the float variant is practically identical except the last 2 digits are indicated to be numbers after the decimal point.

CommandRef|CommandUniqPtr menu.click_slider(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, int min_value, int max_value, int default_value, int step_size, function on_click)
CommandRef|CommandUniqPtr menu.click_slider_float(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, int min_value, int max_value, int default_value, int step_size, function on_click)

Your on_click function will be called with value and click_type.

Note that the float variant is practically identical except the last 2 digits are indicated to be numbers after the decimal point.

CommandRef|CommandUniqPtr menu.list_select(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, table<int, table> options, int default_value, function on_change)

options must be table of list action item data or Label. List action item data is an index-based table that contains at least a Label (menu_name), and can optionally have command_names and help_text.

Your on_change function will be called with the option's index, the option's menu_name, and previous option's index, and click_type as parameters.

CommandRef|CommandUniqPtr menu.list_action(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, table<int, table> options, function on_item_click)

options must be table of list action item data or Label. List action item data is an index-based table that contains at least a Label (menu_name), and can optionally have command_names and help_text.

Your on_item_click function will be called with the option's index, the option's menu_name, and click_type as parameters.

CommandRef|CommandUniqPtr menu.text_input(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, function on_change, string default_value = "")

Your on_change function will be called with the string and click type.

CommandRef|CommandUniqPtr menu.colour(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, Colour default, bool transparency, function on_change)

Your on_change function will be called with a Colour as parameter.

CommandRef|CommandUniqPtr menu.colour(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, number default_r, number default_g, number default_b, number default_a, bool transparency, function on_change)

Your on_change function will be called with a Colour as parameter.

CommandRef|CommandUniqPtr menu.rainbow(CommandRef colour_command)

Creates a rainbow slider for the given colour command. This should be called right after creating the colour command.

CommandRef|CommandUniqPtr menu.divider(CommandRef parent, Label menu_name)
CommandRef|CommandUniqPtr menu.readonly(CommandRef parent, Label menu_name, string value = "")

Pairs well with menu.on_tick_in_viewport and menu.set_value.

CommandRef|CommandUniqPtr menu.hyperlink(CommandRef parent, Label menu_name, string link, Label help_text = "")
CommandRef|CommandUniqPtr menu.action_slider(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, table<int, Label> options, function on_click)

We highly recommend using menu.list_action instead of this, unless the options are really unimportant.

Your on_click function will be called with the option's index, the option's value, and click_type as parameters.

CommandRef|CommandUniqPtr menu.slider_text(CommandRef parent, Label menu_name, table<any, string> command_names, Label help_text, table<int, Label> options, function on_click)

We highly recommend using menu.list_select instead of this, unless the options are really unimportant.

Your on_click function will be called with the option's index, the option's value, and click_type as parameters.

void menu.apply_command_states()

Loads state & hotkeys for commands you've created without needing to yield, although note that your script is always expected to create all (stateful) commands in the first tick.

void menu.delete(CommandRef command)
CommandRef menu.replace(CommandRef old, CommandUniqPtr new)
CommandUniqPtr menu.detach(CommandRef command)
CommandRef menu.attach(CommandRef parent, CommandUniqPtr command)
CommandRef menu.attach_after(CommandRef anchor, CommandUniqPtr command)
CommandRef menu.attach_before(CommandRef anchor, CommandUniqPtr command)
void menu.is_ref_valid(CommandRef ref)

Returns if the referenced command still exists.

void menu.focus(CommandRef command)
bool menu.is_focused(CommandRef command)
table<int, int> menu.get_applicable_players(CommandRef command, ?bool include_user = nil)
CommandRef menu.get_parent(CommandRef command)
int menu.get_type(CommandRef command)

The type may equal one of these values:

  • COMMAND_ACTION
  • COMMAND_ACTION_VALUE
  • COMMAND_ACTION_ITEM
  • COMMAND_ACTION_SLIDER
  • COMMAND_READONLY_NAME
  • COMMAND_READONLY_VALUE
  • COMMAND_READONLY_LINK
  • COMMAND_DIVIDER
  • COMMAND_SLIDER_TEXT
  • COMMAND_LIST
  • COMMAND_LIST_CUSTOM_SPECIAL_MEANING
  • COMMAND_LIST_PLAYER
  • COMMAND_LIST_COLOUR
  • COMMAND_LIST_HISTORICPLAYER
  • COMMAND_LIST_READONLY
  • COMMAND_LIST_REFRESHABLE
  • COMMAND_LIST_CONCEALER
  • COMMAND_LIST_SEARCH
  • COMMAND_LIST_ACTION
  • COMMAND_LIST_SELECT
  • COMMAND_TOGGLE_NO_CORRELATION
  • COMMAND_TOGGLE
  • COMMAND_TOGGLE_CUSTOM
  • COMMAND_SLIDER
  • COMMAND_SLIDER_RAINBOW

List types will return a non-zero value if ANDed with COMMAND_FLAG_LIST.

Additionally, if you AND the type with COMMAND_FULLTYPEFLAG, you may find the result to equal one of the following:

  • COMMAND_FLAG_LIST
  • COMMAND_FLAG_LIST_ACTION
  • COMMAND_FLAG_TOGGLE
  • COMMAND_FLAG_SLIDER
table<int, CommandRef> menu.get_children(CommandRef list)
int menu.collect_garbage()

Removes invalidated weakrefs from an internal vector. Stand does this automatically, but if you bulk-delete-or-replace commands, you might want to call this right after.

bool menu.is_open()
number, number menu.get_position()

Returns the menu grid origin x & y.

number, number, number, number menu.get_main_view_position_and_size()

Returns x, y, width, & height for the current main view (active list, warning, etc.).

CommandRef menu.get_current_menu_list()

Returns a reference to the current menu list, which ignores the context menu.

CommandRef menu.get_current_ui_list()

Returns a reference to the current UI list, which can include the context menu.

string menu.get_active_list_cursor_text(bool even_when_disabled = false, bool even_when_inappropriate = false)

Returns the cursor text of the current UI list.

bool menu.are_tabs_visible()
void menu.show_command_box(string prefill)
void menu.show_command_box_click_based(int click_type, string prefill)
void menu.trigger_commands(string input)
void menu.trigger_command(CommandRef command, string arg)
bool menu.command_box_is_open()
number, number, number, number menu.command_box_get_dimensions()

Returns x, y, width, & height.

bool menu.is_in_screenshot_mode()
int menu.on_tick_in_viewport(CommandRef command, function callback)
int menu.on_focus(CommandRef command, function callback)
int menu.on_blur(CommandRef command, function callback)
bool menu.remove_handler(CommandRef command, int handler_id)
Label menu.get_menu_name(CommandRef|CommandUniqPtr command)

You might want to use lang.get_string on the return value.

table<int, string> menu.get_command_names(CommandRef|CommandUniqPtr command)
Label menu.get_help_text(CommandRef|CommandUniqPtr command)

You might want to use lang.get_string on the return value.

string menu.get_name_for_config(CommandRef|CommandUniqPtr command)
bool menu.get_visible(CommandRef command)
int|bool|string menu.get_value(CommandRef command)
int menu.get_min_value(CommandRef command)
int menu.get_max_value(CommandRef command)
int menu.get_step_size(CommandRef command)
string menu.get_state(CommandRef command)
string menu.get_default_state(CommandRef command)
string menu.apply_default_state(CommandRef command)
void menu.set_menu_name(CommandRef|CommandUniqPtr command, Label menu_name)
void menu.set_command_names(CommandRef|CommandUniqPtr command, table<any, string> command_names)
void menu.set_help_text(CommandRef|CommandUniqPtr command, Label help_text)
void menu.set_name_for_config(CommandRef|CommandUniqPtr command, string name_for_config)

If empty (which is the default), the name for config is the English (UK) translation of the menu_name, but if you change the menu_name of a command or have multiple commands in the same list with the same name, this will help the state and hotkeys system to keep the association.

void menu.set_visible(CommandRef command, bool visible)
void menu.set_value(CommandRef command, int|bool|string value)
void menu.set_min_value(CommandRef command, int min_value)
void menu.set_max_value(CommandRef command, int max_value)
void menu.set_step_size(CommandRef command, int step_size)
void menu.set_list_action_options(CommandRef command, table<int, table> options)

Also works for list_select.

void menu.set_action_slider_options(CommandRef command, table<int, Label> options)

Also works for slider_text.

void menu.set_temporary(CommandRef command)

Commands marked as "temporary" will not have state or hotkey options and can't be added to "Saved Commands." However, they will still have their state set to default in the script stop process.

void menu.show_warning(CommandRef command, int click_type, string message, function proceed_callback, ?function cancel_callback = nil, bool skippable = false)

skippable will not have an effect when "Force Me To Read Warnings" is disabled.

int menu.get_activation_key_hash()

Returns a 32-bit integer derived from the user's activation key. 0 if no activation key.

int menu.get_edition()

Returns a value between 0 and 3 depending on the user's edition.

table<string, string> menu.get_version()
full "Stand 0.93.1" "Stand 0.93.1-preview1"
version "0.93.1" "0.93.1-preview1"
version_target "0.93.1" "0.93.1"
branch nil "preview1"
brand "Stand" "Stand"

§ Players Functions

int players.add_command_hook(function callback)

Registers a function to be called when a player should have script features added. Your callback will be called with the player id and player root as arguments.

Note that although your callback may yield, it should create all player commands in the same tick as it is called.

int players.on_join(function callback)

Registers a function to be called when a player joins the session. Your callback will be called with the player id as argument.

Note that although your callback may yield, it should create all player commands in the same tick as it is called.

int players.on_leave(function callback)

Registers a function to be called when a player leaves the session. Your callback will be called with the player id and name as arguments.

void players.dispatch_on_join()

Calls your join handler(s) for every player that is already in the session.

bool players.exists(int player_id)

Checks if a player with the given id is in session.

int players.user()

Alternative to the PLAYER.PLAYER_ID native.

int players.user_ped()

Alternative to the PLAYER.PLAYER_PED_ID native.

table<int, int> players.list(bool include_user = true, bool include_friends = true, bool include_strangers = true)

Returns an index-based table with all matching player ids.

table<int, int> players.list_all_with_excludes(bool include_user = false)

Like players.list but using Players > All Players > Excludes.

int players.get_host()
int players.get_script_host()
table<int, int> players.get_focused()

Returns an index-based table containing the ids of all players focused in the menu.

string players.get_name(int player_id)
int players.get_rockstar_id(int player_id)

This value might be spoofed by hard RID spoofing.

int players.get_rockstar_id_2(int player_id)

This value might be spoofed by soft RID spoofing.

int players.get_connect_ip(int player_id)
int players.get_connect_port(int player_id)
int players.get_online_ip(int player_id)
int players.get_online_port(int player_id)
int players.get_rank(int player_id)
int players.get_rp(int player_id)
int players.get_money(int player_id)
int players.get_wallet(int player_id)
int players.get_bank(int player_id)
number players.get_kd(int player_id)
int players.get_kills(int player_id)
int players.get_deaths(int player_id)
int players.get_language(int player_id)

Returns the same as the LOCALIZATION.GET_CURRENT_LANGUAGE native.

bool players.is_using_controller(int player_id)
string players.get_name_with_tags(int player_id)
string players.get_tags_string(int player_id)
bool players.is_godmode(int player_id)
bool players.is_marked_as_modder(int player_id)

Returns true if the player has the "Modder" tag.

bool players.is_marked_as_modder_or_admin(int player_id)

Returns true if the player has the "Modder or Admin" tag.

bool players.is_marked_as_admin(int player_id)

Returns true if the player has the "Admin" tag.

bool players.is_marked_as_attacker(int player_id)
bool players.is_otr(int player_id)
bool players.is_in_interior(int player_id)
bool players.is_typing(int player_id)
bool players.is_using_vpn(int player_id)
string players.get_host_token(int player_id)

Returns the player's host token as a decimal string.

string players.get_host_token_hex(int player_id)

Returns the player's host token as a 16-character padded hex string.

string players.get_host_queue_position(int player_id)

Returns the position or 0 if not applicable.

table<int, int> players.get_host_queue(bool include_user = true, bool include_friends = true, bool include_strangers = true)

Returns an index-based table with all matching player ids, sorted in ascending host queue order.

int players.get_boss(int player_id)

Returns -1 if not applicable.

int players.get_org_type(int player_id)

Returns -1 for none, 0 for CEO, or 1 for Motorcycle Club.

int players.get_org_colour(int player_id)

Returns -1 if not applicable. If you want the HUD colour, add 192 to the return value.

string players.clan_get_motto(int player_id)
userdata players.get_position(int player_id)

Works correctly at all distances.

int players.get_vehicle_model(int player_id)

Works at all distances, but best when the user is close to them.

?int players.get_bounty(int player_id)

Returns the value of the player's bounty or nil.

void players.send_sms(int recipient, string text)
void players.send_sms(int recipient, int sender, string text)
Vector3 players.get_cam_pos(int player_id)
Vector3 players.get_cam_rot(int player_id)
number, number, number, bool players.get_waypoint(int player_id)

Returns X, Y, Z, and a bool to indicate if the Z is guessed. Z will always be guessed for remote players.

int players.get_net_player(int player_id)

The address of the player's CNetGamePlayer/rage::netPlayer instance or 0.

int players.set_wanted_level(int player_id, int wanted_level)
int players.give_pickup_reward(int player_id, string|int reward)

Valid rewards can be found in pickups.meta <Rewards> blocks. Some examples are REWARD_HEALTH, REWARD_ARMOUR, REWARD_WEAPON_PISTOL, and REWARD_AMMO_PISTOL. Only works on remote players.

§ Entities Functions

int entities.create_ped(int type, int hash, Vector3 pos, number heading)

A wrapper for the PED.CREATE_PED native.

int entities.create_vehicle(int hash, Vector3 pos, number heading)

A wrapper for the VEHICLE.CREATE_VEHICLE native.

int entities.create_object(int hash, Vector3 pos)

A wrapper for the OBJECT.CREATE_OBJECT_NO_OFFSET native.

int entities.get_user_vehicle_as_handle(bool include_last_vehicle = true)

Returns -1 if vehicle not found.

int entities.get_user_vehicle_as_pointer(bool include_last_vehicle = true)

Returns 0 if vehicle not found.

int entities.get_user_personal_vehicle_as_handle()
int entities.handle_to_pointer(int handle)

Returns the address of the entity with the given script handle.

bool entities.has_handle(int addr)

Returns the entity with the given address has a script handle.

int entities.pointer_to_handle(int addr)

Returns a script handle for the entity with the given address. If the entity does not have a script handle, one will be assigned to it. Note that script handles are a limited resource.

table<int, int> entities.get_all_vehicles_as_handles()

This will force a script handle to be allocated for all vehicles. Note that script handles are a limited resource.

table<int, int> entities.get_all_vehicles_as_pointers()
table<int, int> entities.get_all_peds_as_handles()

This will force a script handle to be allocated for all peds. Note that script handles are a limited resource.

table<int, int> entities.get_all_peds_as_pointers()
table<int, int> entities.get_all_objects_as_handles()

This will force a script handle to be allocated for all objects. Note that script handles are a limited resource.

table<int, int> entities.get_all_objects_as_pointers()
table<int, int> entities.get_all_pickups_as_handles()

This will force a script handle to be allocated for all pickups. Note that script handles are a limited resource.

table<int, int> entities.get_all_pickups_as_pointers()
void entities.delete_by_handle(int handle)
void entities.delete_by_pointer(int addr)
int entities.get_model_hash(int addr)
Vector3 entities.get_position(int addr)

The result might be less precise than the native counterpart.

Vector3 entities.get_rotation(int addr)

The result might be less precise than the native counterpart.

number entities.get_health(int addr)
int entities.get_current_gear(int addr)

Only applicable to vehicles.

void entities.set_current_gear(int addr, int current_gear)

Only applicable to vehicles.

int entities.get_next_gear(int addr)

Only applicable to vehicles.

void entities.set_next_gear(int addr, int next_gear)

Only applicable to vehicles.

number entities.get_rpm(int addr)

Only applicable to vehicles.

number entities.get_gravity(int addr)

Only applicable to vehicles.

number entities.set_gravity(int addr, number gravity)

Only applicable to vehicles.

number entities.set_gravity_multiplier(int addr, number gravity_multiplier)

Only applicable to vehicles.

number entities.get_boost_charge(int addr)

Only applicable to vehicles. Returns a value between 0.0 and 1.25.

int entities.get_draw_handler(int addr)

Returns a pointer or 0.

int entities.vehicle_draw_handler_get_pearlecent_colour(int addr)
int entities.vehicle_draw_handler_get_wheel_colour(int addr)
bool entities.get_vehicle_has_been_owned_by_player(int addr)
int entities.get_player_info(int addr)

Only applicable to peds.

int entities.player_info_get_game_state(int addr)
int entities.get_weapon_manager(int addr)

Only applicable to peds.

int entities.get_owner(int addr)

Returns the ID of the player that owns this entity.

void entities.set_can_migrate(int addr, bool can_migrate)

Prevents ambient ownership changes so that only explicit requests will be processed.

§ Chat Functions

int chat.on_message(function callback)

Registers a function to be called when a chat message is sent:

chat.on_message(function(sender, reserved, text, team_chat, networked, is_auto)
    -- Do stuff...
end)
void chat.send_message(string text, bool team_chat, bool add_to_local_history, bool networked)

As you might be aware, messages have a limit of 140 UTF-16 characters. However, that is only true for the normal input, as you can use up to 254 UTF-8 characters over the network, and many more for the local history.

void chat.send_targeted_message(int recipient, int sender, string text, bool team_chat)

sender will only be respected when recipient == players.user(), otherwise sender will be forced to players.user().

int chat.get_state()

Possible return values:

  • 0 = Closed
  • 1 = Writing in team chat
  • 2 = Writing in all chat
bool chat.is_open()
void chat.open()
void chat.close()
string chat.get_draft()

Returns the message that the user is currently drafting or an empty string if not applicable.

void chat.ensure_open_with_empty_draft(bool team_chat)
void chat.add_to_draft(string appendix)
void chat.remove_from_draft(int characters)

§ DirectX Functions

Any X and Y value must be between 0.0 to 1.0.

The draw functions are in the HUD coordinate space, which is superimposed 1920x1080. You can also append _client to any draw function, e.g. draw_line_client to draw in client coordinate space, which is based on the game window size.

int directx.create_texture(string path)

An absolute path is recommended, e.g. by using filesystem.resources_dir().

void directx.draw_texture(int id, number sizeX, number sizeY, number centerX, number centerY, number posX, number posY, number rotation, Colour colour)
void directx.draw_texture(int id, number sizeX, number sizeY, number centerX, number centerY, number posX, number posY, number rotation, number r, number g, number b, number a)
void directx.draw_text(number x, number y, string text, int alignment, number scale, Colour colour, bool force_in_bounds = false)

alignment can be any of:

  • ALIGN_TOP_LEFT
  • ALIGN_TOP_CENTRE
  • ALIGN_TOP_RIGHT
  • ALIGN_CENTRE_LEFT
  • ALIGN_CENTRE
  • ALIGN_CENTRE_RIGHT
  • ALIGN_BOTTOM_LEFT
  • ALIGN_BOTTOM_CENTRE
  • ALIGN_BOTTOM_RIGHT
void directx.draw_rect(number x, number y, number width, number height, Colour colour)
void directx.draw_line(number x1, number y1, number x2, number y2, Colour colour)
void directx.draw_line(number x1, number y1, number x2, number y2, Colour colour1, Colour colour2)
void directx.draw_triangle(number x1, number y1, number x2, number y2, number x3, number y3, Colour colour)
number, number directx.get_client_size()
number, number directx.get_text_size(string text, number scale = 1.0)

Returns width and height.

number, number directx.pos_hud_to_client(number x, number y)
number, number directx.size_hud_to_client(number x, number y)
number, number directx.pos_client_to_hud(number x, number y)
number, number directx.size_client_to_hud(number x, number y)
int directx.blurrect_new()
void directx.blurrect_free(int instance)

Frees an instance. This is automatically done for all instances your script has allocated but not freed once it finishes.

void directx.blurrect_draw(int instance, number x, number y, number width, number height, int strength)

Prefer to use 1 instance per region, as any draw with a different size requires the buffers to be reallocated.

strength should be around 4 and can't exceed 255.

§ Util Functions

void util.require_natives(int|string version)

Loads the natives lib with the provided version, installing it from the repository if needed.

void util.execute_in_os_thread(function func)

Executes the given function in an OS thread to avoid holding up the game for expensive tasks like using require on a big file, creating lots of commands, or performing expensive calculations. Note that this will hold up your entire script, and calling natives or certain api functions in this context may lead to instabilities.

void util.require_no_lag(string file)

Like require, but in an OS thread, to avoid holding up the game. Might not work for every library.

void util.create_tick_handler(function func)

Registers the parameter-function to be called every tick until it returns false.

void util.try_run(function func)
void util.keep_running()

Prevents Stand cleaning up your script for being idle. This is implicit when you create commands, register event handlers, or use the async_http API.

void util.yield(?int wake_in_ms = nil)

Pauses the execution of the calling thread until the next tick or in wake_in_ms milliseconds.

If you're gonna create a "neverending" loop, don't forget to yield:

while true do
    -- Code that runs every tick...
    util.yield()
end

For simple loops, you should prefer util.create_tick_handler.

void util.set_busy(bool busy)
void util.create_thread(function thread_func, ...)

Creates the kind of thread that your script gets when it is created, or one of your callbacks is invoked, which is just another coroutine that gets resumed every tick and is expected to yield or return.

void util.stop_thread()

Stops the calling thread.

void util.restart_script()

Goes through the script stop process, freshly loads the contents of the script file, and starts the main thread again. Note that the thread scheduler stays as-is, so this restart is different from a stop-and-start.

void util.stop_script()
void util.on_pre_stop(function func)
void util.on_stop(function func)

Script stop process:

  • on_pre_stop handlers are called.
  • Default state is applied to all commands (Change callbacks may be called at this point with CLICK_BULK).
  • on_stop handlers are called.

Note that yielding and creating threads are not available during the stop process.

void util.toast(string message, int bitflags = TOAST_DEFAULT)

Possible bitflags:

  • TOAST_ABOVE_MAP — Uses Stand notifications if enabled
  • TOAST_CONSOLE
  • TOAST_FILE
  • TOAST_WEB
  • TOAST_CHAT
  • TOAST_CHAT_TEAM
  • TOAST_DEFAULT — Equal to (TOAST_ABOVE_MAP | TOAST_WEB)
  • TOAST_LOGGER — Equal to (TOAST_CONSOLE | TOAST_FILE)
  • TOAST_ALL — Equal to (TOAST_DEFAULT | TOAST_LOGGER)

Note that the chat flags are mutually exclusive.

void util.log(string message)

Alias for

util.toast(message, TOAST_LOGGER)

void util.draw_debug_text(string text)

Draws the given text for the current tick using the "Info Text" system.

void util.show_corner_help(string message)

Shorthand for

util.BEGIN_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(message)
if not HUD.END_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(0) then
    util.BEGIN_TEXT_COMMAND_DISPLAY_HELP(message)
    HUD.END_TEXT_COMMAND_DISPLAY_HELP(0, false, true, -1)
end
void util.replace_corner_help(string message, string replacement_message)

Shorthand for

util.BEGIN_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(message)
if HUD.END_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(0) then
    util.BEGIN_TEXT_COMMAND_DISPLAY_HELP(replacement_message)
    HUD.END_TEXT_COMMAND_DISPLAY_HELP(0, false, true, -1)
end
void util.set_local_player_wanted_level(int wanted_level)

Replacement for

PLAYER.SET_PLAYER_WANTED_LEVEL_NO_DROP(PLAYER.PLAYER_ID(), wanted_level, false)
PLAYER.SET_PLAYER_WANTED_LEVEL_NOW(PLAYER.PLAYER_ID(), false)

using pointers to avoid potentially tripping anti-cheat.

int util.joaat(string text)

JOAAT stands for Jenkins One At A Time which is the name of the hashing algorithm used pretty much everywhere in GTA.

string util.reverse_joaat(int hash)

Returns an empty string if the given hash is not found in Stand's dictionaries.

bool util.is_this_model_a_blimp(int|string model)
bool util.is_this_model_an_object(int|string model)
bool util.is_this_model_a_submarine(int|string model)
bool util.is_this_model_a_trailer(int|string model)
table<int, table> util.get_vehicles()

Returns an index-based table with a table for each vehicle in the game. The inner tables contain name and manufacturer.

table<int, table> util.get_weapons()

Returns an index-based table with a table for each weapon in the game. The inner tables contain hash, label_key, category, & category_id. Note that the categories are specific to Stand.

void util.BEGIN_TEXT_COMMAND_DISPLAY_TEXT(string message)

Replacement for

HUD.BEGIN_TEXT_COMMAND_DISPLAY_TEXT("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

void util._BEGIN_TEXT_COMMAND_LINE_COUNT(string message)

Replacement for

HUD._BEGIN_TEXT_COMMAND_LINE_COUNT("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

void util.BEGIN_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(string message)

Replacement for

HUD.BEGIN_TEXT_COMMAND_IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

void util.BEGIN_TEXT_COMMAND_DISPLAY_HELP(string message)

Replacement for

HUD.BEGIN_TEXT_COMMAND_DISPLAY_HELP("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

void util._BEGIN_TEXT_COMMAND_GET_WIDTH(string message)

Replacement for

HUD._BEGIN_TEXT_COMMAND_GET_WIDTH("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

void util.BEGIN_TEXT_COMMAND_THEFEED_POST(string message)

Replacement for

HUD.BEGIN_TEXT_COMMAND_THEFEED_POST("STRING")
HUD.ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(message)

which increases your message's character limit.

int util.get_rp_required_for_rank(int rank)
int util.get_session_players_bitflag()
void util.trigger_script_event(int session_player_bitflags, table<any, int> data)

session_player_bitflags has a bit set to 1 for every player that should receive the script event; you can use util.get_session_players_bitflag() if you intend for everyone to receive the script event or use 1 << player_id to target individual players.

int util.current_time_millis()
int util.current_unix_time_seconds()

Returns how many seconds have passed since the UNIX epoch (00:00:00 UTC on 1 January 1970).

bool util.remove_handler(int handler_id)
bool util.is_session_started()
bool util.is_session_transition_active()
int util.get_char_slot()
bool, number util.get_ground_z(number x, number y, number z_hint = 1000.0)

The most precise way to get the ground Z coordinate which respects water.

The ground Z will be below the z_hint.

If the bool return value is true, the number is the ground Z. If not, you should try again next tick. You may want to count the calls you made and abort after a certain amount of calls with the bool being false.

bool util.spoof_script(string|int script, function func)

If the provided script is not running, your function is not called and this returns false.

bool util.remove_blip(int blip)
void util.arspinner_enable()
void util.arspinner_disable()
bool util.is_bigmap_active()
void util.copy_to_clipboard(string text, bool notify = true)
string util.get_clipboard_text()
table<string,string> util.read_colons_and_tabs_file(string file)

Allows you to read a file in the colons and tabs format, which is what Stand uses for profiles, hotkeys, etc.

void util.write_colons_file(string file, table<string,string> data)

Allows you to write a file in the colons and tabs format.

void util.draw_ar_beacon(Vector3 pos)
void util.draw_box(Vector3 pos, Vector3 rot, Vector3 dimensions, int r, int g, int b, int a = 255)

Draws a box with 3d rotation using polys. Note that backfaceculling applies to the inside.

bool util.request_script_host(string|int script)
bool util.register_file(string path)

Registers the given file in the game so it can be used with natives, e.g. util.register_file(filesystem.resources_dir() .. "myscript.ytd") will allow you to use "myscript" as a texture dict for GRAPHICS natives.

string util.get_label_text(int|string label_key)

Same as HUD._GET_LABEL_TEXT except it will bypass any replacements Stand might be making.

string util.register_label(string text)

Registers a label, such that it can be used with HUD._GET_LABEL_TEXT and other natives.

bool util.is_key_down(int|string vk)

vk int values can be found at https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

vk may also be a string, if it contains a single character and that character is A-Z, 0-9, or a space.

int util.call_foreign_function(int addr, int|userdata|string ...)
string util.get_rtti_name(int inst_addr)
string util.get_rtti_hierarchy(int inst_addr)
void util.set_particle_fx_asset(int|string hash)
int util.blip_handle_to_pointer(int blip_handle)
int util.get_blip_display(int blip_handle)
int util.teleport_2d(number x, number y)
bool util.is_interaction_menu_open()
int util.on_transition_finished(function callback)
int util.get_closest_hud_colour(int target_r, int target_g, int target_b, int target_a = 255)
bool util.is_soup_netintel_inited()
int util.on_pad_shake(function callback)
util.on_pad_shake(function(light_duration, light_intensity, heavy_duration, heavy_intensity, delay_after_this_one)
    -- Do stuff...
end)
void util.request_model(int|string model, int timeout = 2000)

Attempts to load the given model within timeout milliseconds or throws an error.

§ V3 Functions

userdata v3.new(float x, float y, float z)
userdata v3.new(Vector3 pos)
userdata v3.new()

Creates a new v3 instance, which can be used anywhere a Vector3 or Vector3* is accepted.

As an alternative to v3.new(...), you can also use v3(...).

Furthermore, all following functions can be called on a v3 instance using the : syntax.

float, float, float v3.get(userdata|int addr)
float v3.getX(userdata|int addr)
float v3.getY(userdata|int addr)
float v3.getZ(userdata|int addr)
float v3.getHeading(userdata|int addr)
void v3.set(userdata|int addr, float x, float y, float z)
void v3.setX(userdata|int addr, float x)
void v3.setY(userdata|int addr, float y)
void v3.setZ(userdata|int addr, float z)
void v3.reset(userdata|int addr)
void v3.add(userdata|int a, userdata|int b)

Adds b to a.

void v3.sub(userdata|int a, userdata|int b)

Subtracts b from a.

void v3.mul(userdata|int a, number f)

Multiplies a by f.

void v3.div(userdata|int a, number f)

Divides a by f.

bool v3.eq(userdata|int a, userdata|int b)
number v3.magnitude(userdata|int a)

Alternatively, you can use the # syntax on a v3 instance to get its magnitude.

number v3.distance(userdata|int a, int b)
void v3.abs(userdata|int addr)

Ensures that every axis is positive.

void v3.sum(userdata|int addr)
float v3.min(userdata|int addr)

Returns the value of the smallest axis.

float v3.max(userdata|int addr)

Returns the value of the biggest axis.

number v3.dot(userdata|int a, int b)
void v3.normalise(userdata|int addr)
userdata v3.crossProduct(userdata|int a, int b)

The result is a new instance.

userdata v3.toRot(userdata|int addr)

The result is a new instance with rotation data.

userdata v3.lookAt(userdata|int a, int b)

The result is a new instance with rotation data.

userdata v3.toDir(userdata|int addr)

The result is a new instance with direction data. The direction vector will have a magnitude of 1 / it is a unit vector, so you can safely multiply it.

Note that Stand expects/uses what is rotation order 2 for RAGE.

string v3.toString(userdata|int addr)

§ Lang Functions

string lang.get_current()

Returns the current menu language, which could be a 2-letter language code, "en-us", "sex", "uwu", or "hornyuwu".

int lang.register(string text)
void lang.set_translate(string lang_code)

Starts the process of translating labels. lang_code must be a 2-letter language code or "sex".

void lang.translate(int label, string text)
int lang.find(string text, string lang_code = "en")

Finds an existing label using its text. Returns 0 if not found. lang_code must be a 2-letter language code or "sex".

int lang.find_registered(string text, string lang_code = "en")

Similar to lang.find but limited to labels your script has registered.

string lang.get_string(Label label, string lang_code = "en")

lang_code must be a 2-letter language code, "en-us", "sex", "uwu", or "hornyuwu".

string lang.get_localised(Label label)

Similar to lang.get_string but always using the current menu language.

string lang.get_code_for_soup(string lang_code)
bool lang.is_automatically_translated(string lang_code)
bool lang.is_english(string lang_code)

§ Filesystem Functions

string filesystem.appdata_dir()

Possible return value: C:\Users\John\AppData\Roaming\

string filesystem.stand_dir()

Possible return value: C:\Users\John\AppData\Roaming\Stand\

string filesystem.scripts_dir()

Possible return value: C:\Users\John\AppData\Roaming\Stand\Lua Scripts\

string filesystem.resources_dir()

Possible return value: C:\Users\John\AppData\Roaming\Stand\Lua Scripts\resources\

That is the directory dedicated to static content for scripts, e.g. a logo.

string filesystem.store_dir()

Possible return value: C:\Users\John\AppData\Roaming\Stand\Lua Scripts\store\

That is the directory dedicated to dynamic content for scripts, e.g. user configuration that can't be dealt with by proper usage of the state system.

This function also creates the "store" directory if it doesn't exist.

bool filesystem.exists(string path)
bool filesystem.is_regular_file(string path)
bool filesystem.is_dir(string path)
void filesystem.mkdir(string path)
void filesystem.mkdirs(string path)
table<int, string> filesystem.list_files(string path)

Returns an index-based table with all files in the given directory.

for i, path in ipairs(filesystem.list_files(filesystem.scripts_dir())) do
    util.log(path)
end

Note that directories in the resulting table don't end on a \.

§ Async HTTP Functions

void async_http.init(string host, string path, ?function success_func = nil, ?function fail_func = nil)

This will make a GET request unless you use async_http.set_post before calling async_http.dispatch.

On success, your success_func will be called with body, header_fields, status_code, if your script is still alive when the request finishes; the lifetimes are independent.

void async_http.dispatch()

Finish building the async http request and carry it out in separate OS thread.

void async_http.set_post(string content_type, string payload)

Changes the request method, adds Content-Type and Content-Length headers, and sets the payload.

Examples of content_type:

  • application/json
  • application/x-www-form-urlencoded; charset=UTF-8
void async_http.add_header(string key, string value)

§ Memory Functions

int memory.script_global(int global)

Returns the address of the given script global.

int memory.script_local(string|int script, int local)

Returns the address of the given script local or 0 if the script was not found.

userdata memory.alloc(int size = 24)

The default size is 24 so it can fit a Vector3.

userdata memory.alloc_int()

Allocates 4 bytes.

int memory.scan(string pattern)
int memory.scan(string module_name, string pattern)

Scans the game's memory for the given IDA-style pattern. This is an expensive call so ideally you'd only ever scan for a pattern once and then use the resulting address until your script finishes.

int memory.rip(int addr)

Follows an offset from the instruction pointer ("RIP") at the given address.

So, whereas in C++ you might do something like this:

memory::scan("4C 8D 05 ? ? ? ? 48 8D 15 ? ? ? ? 48 8B C8 E8 ? ? ? ? 48 8D 15 ? ? ? ? 48 8D 4C 24 20 E8").add(3).rip().as<const char*>();

You'd do this in Lua (with a check for null-pointer because we're smart):

local addr = memory.scan("4C 8D 05 ? ? ? ? 48 8D 15 ? ? ? ? 48 8B C8 E8 ? ? ? ? 48 8D 15 ? ? ? ? 48 8D 4C 24 20 E8")
if addr == 0 then
    util.toast("pattern scan failed")
else
    util.toast(memory.read_string(memory.rip(addr + 3)))
end
lightuserdata memory.addrof(userdata ud)
int memory.read_byte(int|userdata addr)

Reads an 8-bit integer at the given address.

int memory.read_ubyte(int|userdata addr)

Reads an unsigned 8-bit integer at the given address.

int memory.read_short(int|userdata addr)

Reads a 16-bit integer at the given address.

int memory.read_ushort(int|userdata addr)

Reads an unsigned 16-bit integer at the given address.

int memory.read_int(int|userdata addr)

Reads a 32-bit integer at the given address.

int memory.read_uint(int|userdata addr)

Reads an unsigned 32-bit integer at the given address.

int memory.read_long(int|userdata addr)

Reads a 64-bit integer at the given address.

number memory.read_float(int|userdata addr)
string memory.read_string(int|userdata addr)
void memory.write_byte(int|userdata addr, int value)

Writes an 8-bit integer to the given address.

void memory.write_ubyte(int|userdata addr, int value)

Writes an unsigned 8-bit integer to the given address.

void memory.write_short(int|userdata addr, int value)

Writes a 16-bit integer to the given address.

void memory.write_ushort(int|userdata addr, int value)

Writes an unsigned 16-bit integer to the given address.

void memory.write_int(int|userdata addr, int value)

Writes a 32-bit integer to the given address.

void memory.write_uint(int|userdata addr, int value)

Writes an unsigned 32-bit integer to the given address.

void memory.write_long(int|userdata addr, int value)

Writes a 64-bit integer to the given address.

void memory.write_float(int|userdata addr, number value)
void memory.write_string(int|userdata addr, string value)
void memory.write_vector3(int|userdata addr, Vector3 value)
string memory.get_name_of_this_module()

§ Profiling Functions

void profiling.once(string name, function func)

Executes the given function and prints the time it took to your log.

void profiling.tick(string name, function func)

Executes the given function and shows the time it took via the info text/debug text.