diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 1b58cdc4..502c2da6 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -7900,7 +7900,10 @@ HOOK_ON_DEATH = 21 HOOK_ON_PACKET_RECEIVE = 22 --- @type LuaHookedEventType -HOOK_MAX = 23 +HOOK_USE_ACT_SELECT = 23 + +--- @type LuaHookedEventType +HOOK_MAX = 24 --- @class HudDisplayFlags diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 8e9e9aa6..b42f7175 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -2782,7 +2782,8 @@ | HOOK_ON_OBJECT_RENDER | 20 | | HOOK_ON_DEATH | 21 | | HOOK_ON_PACKET_RECEIVE | 22 | -| HOOK_MAX | 23 | +| HOOK_USE_ACT_SELECT | 23 | +| HOOK_MAX | 24 | [:arrow_up_small:](#) diff --git a/docs/lua/hooks.md b/docs/lua/hooks.md index 1d16d71f..369dbbcf 100644 --- a/docs/lua/hooks.md +++ b/docs/lua/hooks.md @@ -109,6 +109,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh | 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](structs.md#Object) renderedObj | | HOOK_ON_DEATH | Called when the local player dies, return `false` to prevent normal death sequence | [MarioState](structs.md#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 | ### Parameters diff --git a/src/game/level_update.c b/src/game/level_update.c index 872d1fce..5d988279 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1527,8 +1527,14 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { gCurrLevelNum = levelNum; gCurrCourseNum = get_level_course_num(levelNum - 1); - if (gCurrDemoInput != NULL || gCurrCreditsEntry != NULL || gCurrCourseNum == COURSE_NONE) { - return 0; + bool foundHook = false; + bool hookUseActSelect = false; + smlua_call_event_hooks_use_act_select(HOOK_USE_ACT_SELECT, levelNum, &foundHook, &hookUseActSelect); + + if (!foundHook || !hookUseActSelect) { + if (gCurrDemoInput != NULL || gCurrCreditsEntry != NULL || gCurrCourseNum == COURSE_NONE) { + return 0; + } } if (gCurrLevelNum != LEVEL_BOWSER_1 && gCurrLevelNum != LEVEL_BOWSER_2 @@ -1544,6 +1550,10 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { disable_warp_checkpoint(); } + if (foundHook) { + return hookUseActSelect; + } + if (gCurrCourseNum > COURSE_STAGES_MAX || warpCheckpointActive) { return 0; } diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index b19b7d01..fe87bdbb 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -2814,7 +2814,8 @@ char gSmluaConstants[] = "" "HOOK_ON_OBJECT_RENDER = 20\n" "HOOK_ON_DEATH = 21\n" "HOOK_ON_PACKET_RECEIVE = 22\n" -"HOOK_MAX = 23\n" +"HOOK_USE_ACT_SELECT = 23\n" +"HOOK_MAX = 24\n" "HUD_DISPLAY_LIVES = 0\n" "HUD_DISPLAY_COINS = 1\n" "HUD_DISPLAY_STARS = 2\n" diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index 2518aec0..bd7f58ef 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -497,6 +497,35 @@ void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int mo } } +void smlua_call_event_hooks_use_act_select(enum LuaHookedEventType hookType, int value, bool* foundHook, bool* returnValue) { + lua_State* L = gLuaState; + *foundHook = false; + if (L == NULL) { return; } + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + for (int i = 0; i < hook->count; i++) { + s32 prevTop = lua_gettop(L); + + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); + + // push value + lua_pushinteger(L, value); + + // call the callback + if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i])) { + LOG_LUA("Failed to call the callback: %u", hookType); + continue; + } + + // output the return value + if (lua_type(L, -1) == LUA_TBOOLEAN) { + *foundHook = true; + *returnValue = smlua_to_boolean(L, -1); + } + lua_settop(L, prevTop); + } +} + //////////////////// // hooked actions // //////////////////// diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 53b474af..2da70c13 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -34,6 +34,7 @@ enum LuaHookedEventType { HOOK_ON_OBJECT_RENDER, HOOK_ON_DEATH, HOOK_ON_PACKET_RECEIVE, + HOOK_USE_ACT_SELECT, HOOK_MAX, }; @@ -61,6 +62,7 @@ static const char* LuaHookedEventTypeName[] = { "HOOK_ON_OBJECT_RENDER", "HOOK_ON_DEATH", "HOOK_ON_PACKET_RECEIVE", + "HOOK_USE_ACT_SELECT", "HOOK_MAX" }; @@ -81,6 +83,7 @@ void smlua_call_event_hooks_object_param(enum LuaHookedEventType hookType, struc bool smlua_call_event_hooks_ret_int(enum LuaHookedEventType hookType, s32* returnValue); void smlua_call_event_hooks_set_camera_mode_params(enum LuaHookedEventType hookType, struct Camera *c, s16 mode, s16 frames, bool* returnValue); void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex); +void smlua_call_event_hooks_use_act_select(enum LuaHookedEventType hookType, int value, bool* foundHook, bool* returnValue); enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior); const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior); diff --git a/src/pc/lua/utils/smlua_audio_utils.c b/src/pc/lua/utils/smlua_audio_utils.c index d2df0423..e08b0607 100644 --- a/src/pc/lua/utils/smlua_audio_utils.c +++ b/src/pc/lua/utils/smlua_audio_utils.c @@ -9,7 +9,7 @@ #include "bass_audio/bass_audio_helpers.h" #include "pc/debuglog.h" -#define MAX_AUDIO_OVERRIDE 64 +#define MAX_AUDIO_OVERRIDE 128 struct AudioOverride { bool enabled;