Add playmode hooks

This commit is contained in:
EmeraldLockdown 2026-03-21 15:01:49 -05:00
parent fb8fbd1136
commit 17d12bc5ca
7 changed files with 110 additions and 26 deletions

View file

@ -8213,7 +8213,9 @@ HOOK_ON_FIND_FLOOR = 62 --- @type LuaHookedEventType
HOOK_ON_FIND_WATER_LEVEL = 63 --- @type LuaHookedEventType
HOOK_ON_FIND_POISON_GAS_LEVEL = 64 --- @type LuaHookedEventType
HOOK_ON_FIND_SURFACE_ON_RAY = 65 --- @type LuaHookedEventType
HOOK_MAX = 66 --- @type LuaHookedEventType
HOOK_BEFORE_PLAY_MODE_RUN = 66 --- @type LuaHookedEventType
HOOK_ON_PLAY_MODE_RUN = 67 --- @type LuaHookedEventType
HOOK_MAX = 68 --- @type LuaHookedEventType
--- @alias LuaHookedEventType
--- | `HOOK_UPDATE`
@ -8282,6 +8284,8 @@ HOOK_MAX = 66 --- @type LuaHookedEventType
--- | `HOOK_ON_FIND_WATER_LEVEL`
--- | `HOOK_ON_FIND_POISON_GAS_LEVEL`
--- | `HOOK_ON_FIND_SURFACE_ON_RAY`
--- | `HOOK_BEFORE_PLAY_MODE_RUN`
--- | `HOOK_ON_PLAY_MODE_RUN`
--- | `HOOK_MAX`
--- @type integer

View file

@ -3543,7 +3543,9 @@
| HOOK_ON_FIND_WATER_LEVEL | 63 |
| HOOK_ON_FIND_POISON_GAS_LEVEL | 64 |
| HOOK_ON_FIND_SURFACE_ON_RAY | 65 |
| HOOK_MAX | 66 |
| HOOK_BEFORE_PLAY_MODE_RUN | 66 |
| HOOK_ON_PLAY_MODE_RUN | 67 |
| HOOK_MAX | 68 |
- MAX_HOOKED_BEHAVIORS
[:arrow_up_small:](#)

View file

@ -1504,6 +1504,41 @@ UNUSED static s32 play_mode_unused(void) {
return 0;
}
s32 run_current_play_mode() {
s32 changeLevel = 0;
s16 hookPlaymode = sCurrPlayMode;
if (smlua_call_event_hooks(HOOK_BEFORE_PLAY_MODE_RUN, sCurrPlayMode, &hookPlaymode)) {
sCurrPlayMode = hookPlaymode;
}
switch (sCurrPlayMode) {
case PLAY_MODE_NORMAL:
changeLevel = play_mode_normal();
break;
case PLAY_MODE_PAUSED:
if (!network_check_singleplayer_pause()) {
changeLevel = play_mode_normal();
}
if (sCurrPlayMode == PLAY_MODE_PAUSED) {
changeLevel = play_mode_paused();
}
break;
case PLAY_MODE_CHANGE_AREA:
changeLevel = play_mode_change_area();
break;
case PLAY_MODE_CHANGE_LEVEL:
changeLevel = play_mode_change_level();
break;
case PLAY_MODE_FRAME_ADVANCE:
changeLevel = play_mode_frame_advance();
break;
}
smlua_call_event_hooks(HOOK_ON_PLAY_MODE_RUN, sCurrPlayMode);
return changeLevel;
}
void update_menu_level(void) {
// figure out level
s32 curLevel = 0;
@ -1731,29 +1766,7 @@ s32 update_level(void) {
gCurrentArea->localAreaTimer++;
}
switch (sCurrPlayMode) {
case PLAY_MODE_NORMAL:
changeLevel = play_mode_normal();
break;
case PLAY_MODE_PAUSED:
if (!network_check_singleplayer_pause()) {
changeLevel = play_mode_normal();
}
if (sCurrPlayMode == PLAY_MODE_PAUSED) {
changeLevel = play_mode_paused();
}
break;
case PLAY_MODE_CHANGE_AREA:
changeLevel = play_mode_change_area();
break;
case PLAY_MODE_CHANGE_LEVEL:
changeLevel = play_mode_change_level();
break;
case PLAY_MODE_FRAME_ADVANCE:
changeLevel = play_mode_frame_advance();
break;
}
changeLevel = run_current_play_mode();
if (changeLevel) {
reset_volume();

View file

@ -3553,7 +3553,9 @@ char gSmluaConstants[] = ""
"HOOK_ON_FIND_WATER_LEVEL=63\n"
"HOOK_ON_FIND_POISON_GAS_LEVEL=64\n"
"HOOK_ON_FIND_SURFACE_ON_RAY=65\n"
"HOOK_MAX=66\n"
"HOOK_BEFORE_PLAY_MODE_RUN=66\n"
"HOOK_ON_PLAY_MODE_RUN=67\n"
"HOOK_MAX=68\n"
"MAX_HOOKED_BEHAVIORS=1024\n"
"HUD_DISPLAY_LIVES=0\n"
"HUD_DISPLAY_COINS=1\n"

View file

@ -64,3 +64,5 @@ SMLUA_EVENT_HOOK(HOOK_ON_FIND_FLOOR, _, f32 posX, f32 posY, f32 posZ, struct Sur
SMLUA_EVENT_HOOK(HOOK_ON_FIND_WATER_LEVEL, _, f32 x, f32 z, f32 *waterLevel) // Manually defined hook
SMLUA_EVENT_HOOK(HOOK_ON_FIND_POISON_GAS_LEVEL, _, f32 x, f32 z, f32 *gasLevel) // Manually defined hook
SMLUA_EVENT_HOOK(HOOK_ON_FIND_SURFACE_ON_RAY, _, Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos) // Manually defined hook
SMLUA_EVENT_HOOK(HOOK_BEFORE_PLAY_MODE_RUN, HOOK_RETURN_NEVER, s16 playmode, OUTPUT s16 *overridePlaymode)
SMLUA_EVENT_HOOK(HOOK_ON_PLAY_MODE_RUN, HOOK_RETURN_NEVER, s16 playmode)

View file

@ -1863,3 +1863,62 @@ bool smlua_call_event_hooks_HOOK_ON_PACKET_BYTESTRING_RECEIVE(s32 modIndex, s32
}
return hookResult;
}
bool smlua_call_event_hooks_HOOK_BEFORE_PLAY_MODE_RUN(s16 playmode, s16 *overridePlaymode) {
lua_State *L = gLuaState;
if (L == NULL) { return false; }
bool hookResult = false;
struct LuaHookedEvent *hook = &sHookedEvents[HOOK_BEFORE_PLAY_MODE_RUN];
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 playmode
lua_pushinteger(L, playmode);
// call the callback
if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i], hook->modFile[i])) {
LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_BEFORE_PLAY_MODE_RUN], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
continue;
}
hookResult = true;
// return overridePlaymode
if (lua_type(L, -1) == LUA_TNUMBER) {
*overridePlaymode = smlua_to_integer(L, -1);
}
lua_settop(L, prevTop);
}
return hookResult;
}
bool smlua_call_event_hooks_HOOK_ON_PLAY_MODE_RUN(s16 playmode) {
lua_State *L = gLuaState;
if (L == NULL) { return false; }
bool hookResult = false;
struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_PLAY_MODE_RUN];
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 playmode
lua_pushinteger(L, playmode);
// call the callback
if (0 != smlua_call_hook(L, 1, 0, 0, hook->mod[i], hook->modFile[i])) {
LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_ON_PLAY_MODE_RUN], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
continue;
}
hookResult = true;
lua_settop(L, prevTop);
}
return hookResult;
}

View file

@ -82,6 +82,8 @@ enum LuaHookedEventType {
HOOK_ON_FIND_WATER_LEVEL,
HOOK_ON_FIND_POISON_GAS_LEVEL,
HOOK_ON_FIND_SURFACE_ON_RAY,
HOOK_BEFORE_PLAY_MODE_RUN,
HOOK_ON_PLAY_MODE_RUN,
HOOK_MAX,
};