* Add a menu where mods can put their options at * Document mod menu hook functions * Add HOOK_ON_LANGUAGE_CHANGED * Add new Cheats mod * Make player menu disable singleplayer pause * fix some git merge conflicts that weren't resolved (#55) and added -latomic to build flags to fix compile warnings while compiling miniaudio * Remove legacy 'deluxe' field from built-in mods * Lots of improvements to memory safety * Abbreviated hex color parsing Co-Authored-By: Mechstreme <84944335+mechstreme@users.noreply.github.com> --------- Co-authored-by: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Co-authored-by: Mechstreme <84944335+mechstreme@users.noreply.github.com>
16 KiB
⏪ Lua Reference
Hooks
Hooks are a way for SM64 to trigger Lua code, whereas the functions listed in functions allow Lua to trigger SM64 code.
Supported Hooks
- hook_behavior
- hook_chat_command
- hook_event
- hook_mario_action
- hook_on_sync_table_change
- hook_mod_menu_button
- hook_mod_menu_checkbox
- hook_mod_menu_slider
- hook_mod_menu_inputbox
hook_behavior
hook_behavior()
allows Lua mods to override existing behaviors or create new ones.
Parameters
Field | Type | Notes |
---|---|---|
behaviorId | enum BehaviorId | Set to nil to create a new behavior |
objectList | enum ObjectList | |
replaceBehavior | bool |
Prevents the original behavior code from running |
initFunction | Lua Function (Object obj) |
Runs once per object |
loopFunction | Lua Function (Object obj) |
Runs once per frame per object |
behaviorName | string |
Optional, name to give to the behavior |
Returns
Lua Example
function bhv_example_init(obj)
obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
network_init_object(obj, true, nil)
end
function bhv_example_loop(obj)
obj.oPosY = obj.oPosY + 1
end
id_bhvExample = hook_behavior(nil, OBJ_LIST_DEFAULT, true, bhv_example_init, bhv_example_loop, "bhvExample")
hook_chat_command
hook_chat_command()
allows Lua mods to react and respond to chat commands. Chat commands start with the /
character. The function the mod passes to the hook should return true
when the command was valid and false
otherwise.
Parameters
Field | Type |
---|---|
command | string |
description | string |
func | Lua Function (string message) -> bool |
Lua Example
function on_test_command(msg)
if msg == "on" then
djui_chat_message_create("Test: enabled")
return true
elseif msg == "off" then
djui_chat_message_create("Test: disabled")
return true
end
return false
end
hook_chat_command("test", "[on|off] turn test on or off", on_hide_and_seek_command)
hook_event
The lua functions sent to hook_event()
will be automatically called by SM64 when certain events occur.
Hook Event Types
Type | Description | Parameters |
---|---|---|
HOOK_UPDATE | Called once per frame | None |
HOOK_MARIO_UPDATE | Called once per player per frame at the end of a mario update | MarioState mario |
HOOK_BEFORE_MARIO_UPDATE | Called once per player per frame at the beginning of a mario update | MarioState mario |
HOOK_ON_SET_MARIO_ACTION | Called every time a player's current action is changed | MarioState mario |
HOOK_BEFORE_PHYS_STEP | Called once per player per frame before physics code is run, return an integer to cancel it with your own step result | MarioState mario, integer stepType |
HOOK_ALLOW_PVP_ATTACK | Called when one player attacks another, return true to allow the attack |
MarioState attacker, MarioState victim, integer interaction |
HOOK_ON_PVP_ATTACK | Called when one player attacks another | MarioState attacker, MarioState victim, integer interaction |
HOOK_ON_PLAYER_CONNECTED | Called when a player connects | MarioState connector |
HOOK_ON_PLAYER_DISCONNECTED | Called when a player disconnects | MarioState disconnector |
HOOK_ON_HUD_RENDER | Called when the HUD is being rendered | None |
HOOK_ON_HUD_RENDER_BEHIND | Called when the HUD is being rendered, every HUD call in this hook renders behind the vanilla HUD | None |
HOOK_ALLOW_INTERACT | Called before mario interacts with an object, return true to allow the interaction |
MarioState interactor, Object interactee, enum InteractionType interactType |
HOOK_ON_INTERACT | Called when mario interacts with an object | MarioState interactor, Object interactee, enum InteractionType interactType, bool interactValue |
HOOK_ON_LEVEL_INIT | Called when the level is initialized | None |
HOOK_ON_WARP | Called when the local player warps | None |
HOOK_ON_SYNC_VALID | Called when the current area is synchronized | None |
HOOK_ON_OBJECT_UNLOAD | Called when any object is unloaded | Object unloadedObject |
HOOK_ON_SYNC_OBJECT_UNLOAD | Called when any networked object is unloaded | Object unloadedObject |
HOOK_ON_PAUSE_EXIT | Called when the local player exits through the pause screen, return false to prevent the exit |
boolean usedExitToCastle |
HOOK_GET_STAR_COLLECTION_DIALOG | Called when the local player collects a star, return a DialogId to show a message | None |
HOOK_ON_SET_CAMERA_MODE | Called when the camera mode gets set, return false to prevent the camera mode from being set |
Camera, integer mode, integer frames |
HOOK_ON_OBJECT_RENDER | Called right before an object is rendered Note: You must set the hookRender field of the object to a non-zero value |
Object renderedObj |
HOOK_ON_DEATH | Called when the local player dies, return false to prevent normal death sequence |
MarioState localMario |
HOOK_ON_PACKET_RECEIVE | Called when the mod receives a packet that used network_send() or network_send_to() |
table dataTable |
HOOK_USE_ACT_SELECT | Called when the level changes, return true to show act selection screen and false otherwise |
integer levelNum |
HOOK_ON_CHANGE_CAMERA_ANGLE | Called when the player changes the camera mode to Lakitu cam or Mario cam, return false to prevent the change |
integer mode |
HOOK_ON_SCREEN_TRANSITION | Called when the game is about to play a transition, return false to prevent the transition from playing |
integer type |
HOOK_ALLOW_HAZARD_SURFACE | Called once per player per frame. Return false to prevent the player from being affected by lava or quicksand |
MarioState mario, integer hazardType |
HOOK_ON_CHAT_MESSAGE | Called when a chat message gets sent. Return false to prevent the message from being sent |
MarioState messageSender, string messageSent |
HOOK_OBJECT_SET_MODEL | Called when a behavior changes models. Also runs when a behavior spawns | Object obj, integer modelID |
HOOK_CHARACTER_SOUND | Called when mario retrieves a character sound to play, return a character sound or 0 to override it |
MarioState mario, enum CharacterSound characterSound |
HOOK_BEFORE_SET_MARIO_ACTION | Called before Mario's action changes Return an action to change the incoming action or 1 to cancel the action change |
MarioState mario, integer incomingAction |
HOOK_JOINED_GAME | Called when the local player finishes the join process (if the player isn't the host) | None |
HOOK_ON_OBJECT_ANIM_UPDATE | Called when an object's animation is updated | Object objNode |
HOOK_ON_DIALOG | Called when a dialog appears. Return false to prevent it from appearing. Return a second parameter as any string to override the text in the textbox |
integer dialogId |
HOOK_ON_EXIT | Called before the game shuts down | None |
HOOK_DIALOG_SOUND | Called when a dialog box sound is going to play, return a DS_* constant to override the sound |
integer dialogSound |
HOOK_ON_COLLIDE_LEVEL_BOUNDS | Called when a mario collides with the level boundaries | MarioState mario |
HOOK_MIRROR_MARIO_RENDER | Called when a Mirror Mario is rendered | GraphNodeObject mirrorMario |
HOOK_OVERRIDE_PHYS_STEP_DEFACTO_SPEED | Called when slope defacto speed for walking is being calculated, overrides the floor normal in the equation | MarioState mario |
HOOK_ON_OBJECT_LOAD | Called when an object is spawned in | Object obj |
HOOK_ON_PLAY_SOUND | Called when a sound is going to play, return a SOUND_* constant or NO_SOUND to override the sound |
integer soundBits, Vec3f pos |
HOOK_ON_SEQ_LOAD | Called when a sequence is going to play, return a SEQ_* constant to override the sequence. SEQ_SOUND_PLAYER (0) is silence. |
integer player, integer seqID |
HOOK_ON_ATTACK_OBJECT | Called when a player attacks an object. May be double-fired in some cases, you'll need to write special code for this | MarioState attacker, Object victim, integer interactionId |
HOOK_ON_LANGUAGE_CHANGED | Called when the language is changed | string language |
Parameters
Field | Type |
---|---|
hook_event_type | HookEventType |
func | Lua Function (... ) |
Lua Example
The following example will print out a message 16 times per frame (once for every possible player).
function mario_update(m)
print("Mario update was called for player index ", m.playerIndex)
end
hook_event(HOOK_MARIO_UPDATE, mario_update)
hook_mario_action
hook_mario_action()
allows Lua mods to create new actions or override existing ones.
Parameters
Field | Type |
---|---|
action_id | integer |
func | Table with entries for Action Hook Types of Lua Function (MarioState m) |
interaction_type | enum InteractionFlag |
Action Hook Types
Type | Description | Returns |
---|---|---|
every_frame | Main action code, called once per frame | true if action cancelled, else false |
gravity | Called inside apply_gravity when in action |
Unused |
Lua Example
ACT_WALL_SLIDE = (0x0BF | ACT_FLAG_AIR | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
function act_wall_slide(m)
if (m.input & INPUT_A_PRESSED) ~= 0 then
local rc = set_mario_action(m, ACT_TRIPLE_JUMP, 0)
m.vel.y = 72.0
if m.forwardVel < 20.0 then
m.forwardVel = 20.0
end
m.wallKickTimer = 0
return rc
end
-- attempt to stick to the wall a bit. if it's 0, sometimes you'll get kicked off of slightly sloped walls
mario_set_forward_vel(m, -1.0)
m.particleFlags = m.particleFlags | PARTICLE_DUST
play_sound(SOUND_MOVING_TERRAIN_SLIDE + m.terrainSoundAddend, m.marioObj.header.gfx.cameraToObject)
set_mario_animation(m, MARIO_ANIM_START_WALLKICK)
if perform_air_step(m, 0) == AIR_STEP_LANDED then
mario_set_forward_vel(m, 0.0)
if check_fall_damage_or_get_stuck(m, ACT_HARD_BACKWARD_GROUND_KB) == 0 then
return set_mario_action(m, ACT_FREEFALL_LAND, 0)
end
end
m.actionTimer = m.actionTimer + 1
if m.wall == nil and m.actionTimer > 2 then
mario_set_forward_vel(m, 0.0)
return set_mario_action(m, ACT_FREEFALL, 0)
end
return 0
end
function act_wall_slide_gravity(m)
m.vel.y = m.vel.y - 2
if m.vel.y < -15 then
m.vel.y = -15
end
end
function mario_on_set_action(m)
-- wall slide
if m.action == ACT_SOFT_BONK then
m.faceAngle.y = m.faceAngle.y + 0x8000
set_mario_action(m, ACT_WALL_SLIDE, 0)
end
end
hook_event(HOOK_ON_SET_MARIO_ACTION, mario_on_set_action)
hook_mario_action(ACT_WALL_SLIDE, { every_frame = act_wall_slide, gravity = act_wall_slide_gravity } )
hook_on_sync_table_change
hook_on_sync_table_change()
allows Lua mods to react to sync table changes.
syncTable
parameter must be a sync table, e.g. gGlobalSyncTable, gPlayerSyncTable[], or one of their child tables.field
parameter must be one of the fields in theSyncTable
.tag
parameter can be any type, and is automatically passed to the callback.func
parameter must be a function with three parameters:tag
,oldVal
, andnewVal
.tag
will be the sametag
passed intohook_on_sync_table_change()
.oldVal
will be the value before it was set.newVal
will be the value that it was set to.
Parameters
Field | Type |
---|---|
syncTable | SyncTable |
field | value |
tag | value |
func | Lua Function (value tag, value oldValue, value newValue) |
Lua Example
function on_testing_field_changed(tag, oldVal, newVal)
print("testingField changed:", tag, ",", oldVal, "->", newVal)
end
hook_on_sync_table_change(gGlobalSyncTable, "testingField", "tag", on_testing_field_changed)
-- now when testingField is set, either locally or over the network on_testing_field_changed() will be called
gGlobalSyncTable.testingField = "hello"
hook_mod_menu_button
hook_mod_menu_button()
allows Lua to add buttons to their designated mod menu submenu.
Parameters
Field | Type |
---|---|
message | string |
func | Lua Function (integer index) |
Lua Example
local menu1Open = false
local menu2Open = false
--- @param index integer
local function on_open_menu(index)
if index == 0 then
menu1Open = true
menu2Open = false
else
menu1Open = false
menu2Open = true
end
end
-- you can always do separate functions too!
hook_mod_menu_button("Open Menu 1", on_open_menu)
hook_mod_menu_button("Open Menu 2", on_open_menu)
hook_mod_menu_checkbox
hook_mod_menu_checkbox()
allows Lua to add checkboxes to their designated mod menu submenu.
Parameters
Field | Type |
---|---|
message | string |
defaultValue | boolean |
func | Lua Function (integer index, boolean value) |
Lua Example
local flyMode = false
local noclipMode = false
--- @param index integer
--- @param value boolean
local function on_set_player_mode(index, value)
if index == 0 then
flyMode = value
else
noclipMode = value
end
end
-- you can always do separate functions too!
hook_mod_menu_checkbox("Fly Mode", false, on_set_player_mode)
hook_mod_menu_checkbox("Noclip Mode", false, on_set_player_mode)
hook_mod_menu_slider
hook_mod_menu_slider()
allows Lua to add sliders to their designated mod menu submenu.
Parameters
Field | Type |
---|---|
message | string |
defaultValue | integer |
min | integer |
max | integer |
func | Lua Function (integer index, integer value) |
Lua Example
local timeScale = 0.0
local function on_set_time_scale(index, value)
timeScale = value
end
hook_mod_menu_slider("Time Scale", 1, 0, 10, on_set_time_scale)
hook_mod_menu_inputbox
hook_mod_menu_inputbox()
allows Lua to add textboxes to their designated mod menu submenu.
Parameters
Field | Type |
---|---|
message | string |
defaultValue | string |
stringLength | integer |
func | Lua Function (integer index, string value) |
Lua Example
--- @param index integer
--- @param value string
local function on_set_network_player_description(index, value)
network_player_set_description(gNetworkPlayers[0], value, 255, 255, 255, 255)
end
hook_mod_menu_inputbox("Network Player Description", on_set_network_player_description)