diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 53eeb9432..cda368310 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -8866,7 +8866,8 @@ HOOK_ON_GEO_PROCESS_CHILDREN = 50 --- @type LuaHookedEventType HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS = 51 --- @type LuaHookedEventType HOOK_ON_INTERACTIONS = 52 --- @type LuaHookedEventType HOOK_ALLOW_FORCE_WATER_ACTION = 53 --- @type LuaHookedEventType -HOOK_MAX = 54 --- @type LuaHookedEventType +HOOK_BEFORE_WARP = 54 --- @type LuaHookedEventType +HOOK_MAX = 55 --- @type LuaHookedEventType --- @alias LuaHookedEventType --- | `HOOK_UPDATE` @@ -8923,6 +8924,7 @@ HOOK_MAX = 54 --- @type LuaHookedEventType --- | `HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS` --- | `HOOK_ON_INTERACTIONS` --- | `HOOK_ALLOW_FORCE_WATER_ACTION` +--- | `HOOK_BEFORE_WARP` --- | `HOOK_MAX` ACTION_HOOK_EVERY_FRAME = 0 --- @type LuaActionHookType diff --git a/data/dynos_warps.cpp b/data/dynos_warps.cpp index 0d86f2a7d..41185fbdd 100644 --- a/data/dynos_warps.cpp +++ b/data/dynos_warps.cpp @@ -260,7 +260,7 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) { } // lua hooks - smlua_call_event_hooks(HOOK_ON_WARP); + smlua_call_event_hooks_warp_params(HOOK_ON_WARP, sWarpDest.type, sWarpDest.levelNum, sWarpDest.areaIdx, sWarpDest.nodeId, sWarpDest.arg); // Reset values sDynosWarpTargetArea = -1; @@ -405,7 +405,7 @@ static void *DynOS_Warp_UpdateExit(void *aCmd, bool aIsLevelInitDone) { sDynosExitTargetWarp = NULL; // lua hooks - smlua_call_event_hooks(HOOK_ON_WARP); + smlua_call_event_hooks_warp_params(HOOK_ON_WARP, sWarpDest.type, sWarpDest.levelNum, sWarpDest.areaIdx, sWarpDest.nodeId, sWarpDest.arg); } // Phase 4 - Unlock Mario as soon as the second transition is ended diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 1ce6304e3..1d343fc60 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -3770,7 +3770,8 @@ | HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS | 51 | | HOOK_ON_INTERACTIONS | 52 | | HOOK_ALLOW_FORCE_WATER_ACTION | 53 | -| HOOK_MAX | 54 | +| HOOK_BEFORE_WARP | 54 | +| HOOK_MAX | 55 | ### [enum LuaActionHookType](#LuaActionHookType) | Identifier | Value | diff --git a/src/game/level_update.c b/src/game/level_update.c index fb76e1065..e8ca64d7a 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -548,7 +548,7 @@ void init_mario_after_warp(void) { gMarioState->skipWarpInteractionsTimer = 30; } - smlua_call_event_hooks(HOOK_ON_WARP); + smlua_call_event_hooks_warp_params(HOOK_ON_WARP, sWarpDest.type, sWarpDest.levelNum, sWarpDest.areaIdx, sWarpDest.nodeId, sWarpDest.arg); } // used for warps inside one level @@ -755,7 +755,10 @@ s16 music_changed_through_warp(s16 arg) { /** * Set the current warp type and destination level/area/node. */ -void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg) { +void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg) {// + + smlua_call_event_hooks_before_warp(HOOK_BEFORE_WARP, &destLevel, &destArea, &destWarpNode, &arg); + if (destWarpNode >= WARP_NODE_CREDITS_MIN) { sWarpDest.type = WARP_TYPE_CHANGE_LEVEL; } else if (destLevel != gCurrLevelNum) { @@ -1846,7 +1849,7 @@ s32 init_level(void) { if (gNetworkPlayerLocal != NULL) { network_player_update_course_level(gNetworkPlayerLocal, gCurrCourseNum, gCurrActStarNum, gCurrLevelNum, gCurrAreaIndex); } - smlua_call_event_hooks(HOOK_ON_LEVEL_INIT); + smlua_call_event_hooks_warp_params(HOOK_ON_LEVEL_INIT, sWarpDest.type, sWarpDest.levelNum, sWarpDest.areaIdx, sWarpDest.nodeId, sWarpDest.arg); // clear texture 1 on level init -- can linger and corrupt textures otherwise extern u8 gGfxPcResetTex1; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index ce307f655..5e4c6361a 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3631,7 +3631,8 @@ char gSmluaConstants[] = "" "HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS=51\n" "HOOK_ON_INTERACTIONS=52\n" "HOOK_ALLOW_FORCE_WATER_ACTION=53\n" -"HOOK_MAX=54\n" +"HOOK_BEFORE_WARP=54\n" +"HOOK_MAX=55\n" "ACTION_HOOK_EVERY_FRAME=0\n" "ACTION_HOOK_GRAVITY=1\n" "ACTION_HOOK_MAX=2\n" diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index aaaed5510..de496ac1e 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -629,6 +629,33 @@ void smlua_call_event_hooks_int_params_ret_int(enum LuaHookedEventType hookType, } } +void smlua_call_event_hooks_warp_params(enum LuaHookedEventType hookType, u8 type, s16 levelNum, u8 areaIdx, u8 nodeId, u32 arg) { + lua_State* L = gLuaState; + 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 params + lua_pushinteger(L, type); + lua_pushinteger(L, levelNum); + lua_pushinteger(L, areaIdx); + lua_pushinteger(L, nodeId); + lua_pushinteger(L, arg); + + // call the callback + if (0 != smlua_call_hook(L, 5, 0, 0, hook->mod[i])) { + LOG_LUA("Failed to call the callback: %u", hookType); + continue; + } + + lua_settop(L, prevTop); + } +} + void smlua_call_event_hooks_int_params_ret_string(enum LuaHookedEventType hookType, s32 param, char** returnValue) { lua_State* L = gLuaState; if (L == NULL) { return; } @@ -725,6 +752,61 @@ void smlua_call_event_hooks_on_play_sound(enum LuaHookedEventType hookType, s32 } } +void smlua_call_event_hooks_before_warp(enum LuaHookedEventType hookType, s16 *destLevel, s16 *destArea, s16 *destWarpNode, s32 *arg) { + lua_State *L = gLuaState; + if (L == NULL) { return; } + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + for (int i = 0; i < hook->count; i++) { + int prevTop = lua_gettop(L); + + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); + + lua_pushinteger(L, *destLevel); + lua_pushinteger(L, *destArea); + lua_pushinteger(L, *destWarpNode); + lua_pushinteger(L, *arg); + + if (smlua_call_hook(L, 4, 1, 0, hook->mod[i]) != 0) { + LOG_LUA("Failed to call the callback: %u", hookType); + lua_settop(L, prevTop); + continue; + } + + // if the hook returns a table, use it to override the warp parameters + if (lua_istable(L, -1)) { + lua_getfield(L, -1, "destLevel"); + if (lua_isnumber(L, -1)) { + *destLevel = (s16)lua_tointeger(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "destArea"); + if (lua_isnumber(L, -1)) { + *destArea = (s16)lua_tointeger(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "destWarpNode"); + if (lua_isnumber(L, -1)) { + *destWarpNode = (s16)lua_tointeger(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "arg"); + if (lua_isnumber(L, -1)) { + *arg = (s32)lua_tointeger(L, -1); + } + lua_pop(L, 1); + + lua_settop(L, prevTop); + return; + } + lua_settop(L, prevTop); + } +} + + void smlua_call_event_hooks_on_seq_load(enum LuaHookedEventType hookType, u32 player, u32 seqId, s32 loadAsync, s16* returnValue) { lua_State* L = gLuaState; if (L == NULL) { return; } diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 8fea7c460..8314d7e4e 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -66,6 +66,7 @@ enum LuaHookedEventType { HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS, HOOK_ON_INTERACTIONS, HOOK_ALLOW_FORCE_WATER_ACTION, + HOOK_BEFORE_WARP, HOOK_MAX, }; @@ -124,6 +125,7 @@ static const char* LuaHookedEventTypeName[] = { "HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS", "HOOK_ON_INTERACTIONS", "HOOK_ALLOW_FORCE_WATER_ACTION", + "HOOK_BEFORE_WARP", "HOOK_MAX" }; @@ -204,6 +206,8 @@ bool smlua_call_event_hooks_mario_param_and_int_and_int_ret_int(enum LuaHookedEv void smlua_call_event_hooks_graph_node_object_and_int_param(enum LuaHookedEventType hookType, struct GraphNodeObject* node, s32 param); void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hookType, struct GraphNode* node, s16 matIndex); void smlua_call_event_hooks_on_seq_load(enum LuaHookedEventType hookType, u32 player, u32 seqId, s32 loadAsync, s16* returnValue); +void smlua_call_event_hooks_before_warp(enum LuaHookedEventType hookType, s16 *destLevel, s16 *destArea, s16 *destWarpNode, s32 *arg); +void smlua_call_event_hooks_warp_params(enum LuaHookedEventType hookType, u8 type, s16 levelNum, u8 areaIdx, u8 nodeId, u32 arg); const char *smlua_call_event_hooks_int_ret_bool_and_string(enum LuaHookedEventType hookType, s32 param, bool* returnValue); void smlua_call_event_hooks_string_param(enum LuaHookedEventType hookType, const char* string);