From 2c367b556dcf113c87f59d1c3e616c38021d4ace Mon Sep 17 00:00:00 2001 From: djoslin0 Date: Sun, 15 Mar 2026 06:04:36 -0700 Subject: [PATCH] Add surface collision Lua hooks (#1139) * Add surface collision Lua hooks - Add 6 new hooks: HOOK_ON_FIND_WALL_COLLISION, HOOK_ON_FIND_CEIL, HOOK_ON_FIND_FLOOR, HOOK_ON_FIND_WATER_LEVEL, HOOK_ON_FIND_POISON_GAS_LEVEL, HOOK_ON_FIND_SURFACE_ON_RAY - Hooks expose current result values and allow overriding collision outputs from Lua * Remove unnecessary branches --------- Co-authored-by: MysterD --- autogen/lua_definitions/constants.lua | 14 +- autogen/lua_definitions/manual.lua | 2 +- docs/lua/constants.md | 8 +- docs/lua/guides/hooks.md | 6 + src/engine/surface_collision.c | 17 ++ src/pc/lua/smlua_constants_autogen.c | 8 +- src/pc/lua/smlua_hook_events.inl | 6 + src/pc/lua/smlua_hooks.c | 305 +++++++++++++++++++++++++- src/pc/lua/smlua_hooks.h | 8 + 9 files changed, 368 insertions(+), 6 deletions(-) diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 8e160c5d4..5bbb7065a 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -8207,7 +8207,13 @@ HOOK_MARIO_OVERRIDE_FLOOR_CLASS = 56 --- @type LuaHookedEventType HOOK_ON_ADD_SURFACE = 57 --- @type LuaHookedEventType HOOK_ON_CLEAR_AREAS = 58 --- @type LuaHookedEventType HOOK_ON_PACKET_BYTESTRING_RECEIVE = 59 --- @type LuaHookedEventType -HOOK_MAX = 60 --- @type LuaHookedEventType +HOOK_ON_FIND_WALL_COLLISION = 60 --- @type LuaHookedEventType +HOOK_ON_FIND_CEIL = 61 --- @type LuaHookedEventType +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 --- @alias LuaHookedEventType --- | `HOOK_UPDATE` @@ -8270,6 +8276,12 @@ HOOK_MAX = 60 --- @type LuaHookedEventType --- | `HOOK_ON_ADD_SURFACE` --- | `HOOK_ON_CLEAR_AREAS` --- | `HOOK_ON_PACKET_BYTESTRING_RECEIVE` +--- | `HOOK_ON_FIND_WALL_COLLISION` +--- | `HOOK_ON_FIND_CEIL` +--- | `HOOK_ON_FIND_FLOOR` +--- | `HOOK_ON_FIND_WATER_LEVEL` +--- | `HOOK_ON_FIND_POISON_GAS_LEVEL` +--- | `HOOK_ON_FIND_SURFACE_ON_RAY` --- | `HOOK_MAX` --- @type integer diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua index 2ba4a4366..2ce161f8a 100644 --- a/autogen/lua_definitions/manual.lua +++ b/autogen/lua_definitions/manual.lua @@ -127,7 +127,7 @@ function update_chat_command_description(command, description) end --- @param hookEventType LuaHookedEventType When a function should run ---- @param func fun(...: any): any The function to run +--- @param func fun(...: any): any?, any? The function to run --- Different hooks can pass in different parameters and have different return values. Be sure to read the hooks guide for more information. function hook_event(hookEventType, func) -- ... diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 0c92edac9..cf00279f7 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -3537,7 +3537,13 @@ | HOOK_ON_ADD_SURFACE | 57 | | HOOK_ON_CLEAR_AREAS | 58 | | HOOK_ON_PACKET_BYTESTRING_RECEIVE | 59 | -| HOOK_MAX | 60 | +| HOOK_ON_FIND_WALL_COLLISION | 60 | +| HOOK_ON_FIND_CEIL | 61 | +| HOOK_ON_FIND_FLOOR | 62 | +| HOOK_ON_FIND_WATER_LEVEL | 63 | +| HOOK_ON_FIND_POISON_GAS_LEVEL | 64 | +| HOOK_ON_FIND_SURFACE_ON_RAY | 65 | +| HOOK_MAX | 66 | - MAX_HOOKED_BEHAVIORS [:arrow_up_small:](#) diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md index af1226bae..07d522650 100644 --- a/docs/lua/guides/hooks.md +++ b/docs/lua/guides/hooks.md @@ -151,6 +151,12 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh | HOOK_MARIO_OVERRIDE_FLOOR_CLASS | Called when Mario's floor class logic updates, return a `SURFACE_CLASS_*` constant to override the type. | [MarioState](../structs.md#MarioState) mario, `integer` surfaceClass | | HOOK_ON_ADD_SURFACE | Called when collision surfaces are added. | [Surface](../structs.md#Surface) surface, `boolean` dynamic | | HOOK_ON_CLEAR_AREAS | Called when a level's areas are unloaded. | None | +| HOOK_ON_FIND_WALL_COLLISION | Called after wall collision detection completes. You can modify the `colData` fields directly. Return a number to override `numCollisions` | `number` posX, `number` posY, `number` posZ, [WallCollisionData](../structs.md#WallCollisionData) colData | +| HOOK_ON_FIND_CEIL | Called after ceiling detection completes. Return `height` to override height, or `height, surface` to override both | `number` posX, `number` posY, `number` posZ, [Surface](../structs.md#Surface) ceil, `number` height | +| HOOK_ON_FIND_FLOOR | Called after floor detection completes. Return `height` to override height, or `height, surface` to override both | `number` posX, `number` posY, `number` posZ, [Surface](../structs.md#Surface) floor, `number` height | +| HOOK_ON_FIND_WATER_LEVEL | Called after water level detection completes. Return a number to override the water level | `number` x, `number` z, `number` waterLevel | +| HOOK_ON_FIND_POISON_GAS_LEVEL | Called after poison gas level detection completes. Return a number to override the gas level | `number` x, `number` z, `number` gasLevel | +| HOOK_ON_FIND_SURFACE_ON_RAY | Called after ray-surface intersection completes. Return `surface` to override the hit surface, or `surface, hitPos` to override both | `Vec3f` orig, `Vec3f` dir, [Surface](../structs.md#Surface) hitSurface, `Vec3f` hitPos | ### Parameters diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 15f6f9a9f..97414235e 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -12,6 +12,7 @@ #include "game/hardcoded.h" #include "pc/utils/misc.h" #include "pc/network/network.h" +#include "pc/lua/smlua_hooks.h" Vec3f gFindWallDirection = { 0 }; u8 gFindWallDirectionActive = false; @@ -343,6 +344,9 @@ s32 find_wall_collisions(struct WallCollisionData *colData) { s32 numCollisions = 0; s16 x = colData->x; s16 z = colData->z; + f32 posX = colData->x; + f32 posY = colData->y; + f32 posZ = colData->z; colData->numWalls = 0; @@ -371,6 +375,8 @@ s32 find_wall_collisions(struct WallCollisionData *colData) { // Increment the debug tracker. gNumCalls.wall += 1; + smlua_call_event_hooks(HOOK_ON_FIND_WALL_COLLISION, posX, posY, posZ, colData, &numCollisions); + return numCollisions; } @@ -544,6 +550,8 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, RET struct Surface **pceil) { // Increment the debug tracker. gNumCalls.ceil += 1; + smlua_call_event_hooks(HOOK_ON_FIND_CEIL, posX, posY, posZ, pceil, &height); + return height; } @@ -882,6 +890,8 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, RET struct Surface **pfloor) { // Increment the debug tracker. gNumCalls.floor += 1; + smlua_call_event_hooks(HOOK_ON_FIND_FLOOR, xPos, yPos, zPos, pfloor, &height); + return height; } @@ -922,6 +932,8 @@ f32 find_water_level(f32 x, f32 z) { } } + smlua_call_event_hooks(HOOK_ON_FIND_WATER_LEVEL, x, z, &waterLevel); + return waterLevel; } @@ -963,6 +975,8 @@ f32 find_poison_gas_level(f32 x, f32 z) { } } + smlua_call_event_hooks(HOOK_ON_FIND_POISON_GAS_LEVEL, x, z, &gasLevel); + return gasLevel; } @@ -1227,6 +1241,7 @@ void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Ve if (normalized_dir[1] >= 1.0f || normalized_dir[1] <= -1.0f) { find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length); + smlua_call_event_hooks(HOOK_ON_FIND_SURFACE_ON_RAY, orig, dir, hit_surface, hit_pos); return; } @@ -1249,4 +1264,6 @@ void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Ve cellX = (s16)fCellX; cellZ = (s16)fCellZ; } + + smlua_call_event_hooks(HOOK_ON_FIND_SURFACE_ON_RAY, orig, dir, hit_surface, hit_pos); } diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index d7ca5a882..60737b707 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3547,7 +3547,13 @@ char gSmluaConstants[] = "" "HOOK_ON_ADD_SURFACE=57\n" "HOOK_ON_CLEAR_AREAS=58\n" "HOOK_ON_PACKET_BYTESTRING_RECEIVE=59\n" -"HOOK_MAX=60\n" +"HOOK_ON_FIND_WALL_COLLISION=60\n" +"HOOK_ON_FIND_CEIL=61\n" +"HOOK_ON_FIND_FLOOR=62\n" +"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" "MAX_HOOKED_BEHAVIORS=1024\n" "HUD_DISPLAY_LIVES=0\n" "HUD_DISPLAY_COINS=1\n" diff --git a/src/pc/lua/smlua_hook_events.inl b/src/pc/lua/smlua_hook_events.inl index 16bbbaee2..71f4a915c 100644 --- a/src/pc/lua/smlua_hook_events.inl +++ b/src/pc/lua/smlua_hook_events.inl @@ -58,3 +58,9 @@ SMLUA_EVENT_HOOK(HOOK_MARIO_OVERRIDE_FLOOR_CLASS, HOOK_RETURN_ON_OUTPUT_SET, str SMLUA_EVENT_HOOK(HOOK_ON_ADD_SURFACE, HOOK_RETURN_NEVER, struct Surface *surface, bool dynamic) SMLUA_EVENT_HOOK(HOOK_ON_CLEAR_AREAS, HOOK_RETURN_NEVER) SMLUA_EVENT_HOOK(HOOK_ON_PACKET_BYTESTRING_RECEIVE, HOOK_RETURN_NEVER, s32 modIndex, s32 valueIndex) +SMLUA_EVENT_HOOK(HOOK_ON_FIND_WALL_COLLISION, _, f32 posX, f32 posY, f32 posZ, struct WallCollisionData *colData, s32 *numCollisions) // Manually defined hook +SMLUA_EVENT_HOOK(HOOK_ON_FIND_CEIL, _, f32 posX, f32 posY, f32 posZ, struct Surface **pceil, f32 *height) // Manually defined hook +SMLUA_EVENT_HOOK(HOOK_ON_FIND_FLOOR, _, f32 posX, f32 posY, f32 posZ, struct Surface **pfloor, f32 *height) // Manually defined hook +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 diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index fc1dafcae..0984c8223 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -26,6 +26,9 @@ #include "game/print.h" #include "gfx_dimensions.h" +extern void smlua_new_vec3f(Vec3f src); +extern void smlua_get_vec3f(Vec3f dest, int index); + #define MAX_HOOKED_REFERENCES 64 #define LUA_BEHAVIOR_FLAG (1 << 15) @@ -172,7 +175,6 @@ bool smlua_call_event_hooks_HOOK_ON_NAMETAGS_RENDER(s32 playerIndex, Vec3f pos, lua_pushinteger(L, playerIndex); // push pos - extern void smlua_new_vec3f(Vec3f src); smlua_new_vec3f(pos); // call the callback @@ -203,7 +205,6 @@ bool smlua_call_event_hooks_HOOK_ON_NAMETAGS_RENDER(s32 playerIndex, Vec3f pos, // pos lua_getfield(L, -1, "pos"); if (lua_type(L, -1) == LUA_TTABLE) { - extern void smlua_get_vec3f(Vec3f dest, int index); smlua_get_vec3f(pos, -1); override = true; } @@ -220,6 +221,306 @@ bool smlua_call_event_hooks_HOOK_ON_NAMETAGS_RENDER(s32 playerIndex, Vec3f pos, return false; } +bool smlua_call_event_hooks_HOOK_ON_FIND_WALL_COLLISION(f32 posX, f32 posY, f32 posZ, struct WallCollisionData *colData, s32 *numCollisions) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_WALL_COLLISION]; + 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 posX, posY, posZ + lua_pushnumber(L, posX); + lua_pushnumber(L, posY); + lua_pushnumber(L, posZ); + + // push colData + smlua_push_object(L, LOT_WALLCOLLISIONDATA, colData, NULL); + + // call the callback (4 args, 1 result) + if (0 != smlua_call_hook(L, 4, 1, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_WALL_COLLISION]); + lua_settop(L, prevTop); + continue; + } + + // return number overrides numCollisions + if (lua_type(L, -1) == LUA_TNUMBER) { + *numCollisions = smlua_to_integer(L, -1); + lua_settop(L, prevTop); + sInHook = false; + return true; + } + + lua_settop(L, prevTop); + } + sInHook = false; + return false; +} + +bool smlua_call_event_hooks_HOOK_ON_FIND_CEIL(f32 posX, f32 posY, f32 posZ, struct Surface **pceil, f32 *height) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_CEIL]; + 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 posX, posY, posZ + lua_pushnumber(L, posX); + lua_pushnumber(L, posY); + lua_pushnumber(L, posZ); + + // push current ceil surface (or nil) + if (pceil && *pceil) { + smlua_push_object(L, LOT_SURFACE, *pceil, NULL); + } else { + lua_pushnil(L); + } + + // push current height + lua_pushnumber(L, *height); + + // call the callback (5 args, 2 results) + if (0 != smlua_call_hook(L, 5, 2, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_CEIL]); + lua_settop(L, prevTop); + continue; + } + + bool override = false; + + // first return value: height (number) + if (lua_type(L, -2) == LUA_TNUMBER) { + *height = smlua_to_number(L, -2); + override = true; + } + + // second return value: surface (userdata) + if (lua_type(L, -1) == LUA_TUSERDATA) { + struct Surface *surface = (struct Surface *)smlua_to_cobject(L, -1, LOT_SURFACE); + if (surface && pceil) { + *pceil = surface; + override = true; + } + } + + lua_settop(L, prevTop); + if (override) { sInHook = false; return true; } + } + sInHook = false; + return false; +} + +bool smlua_call_event_hooks_HOOK_ON_FIND_FLOOR(f32 posX, f32 posY, f32 posZ, struct Surface **pfloor, f32 *height) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_FLOOR]; + 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 posX, posY, posZ + lua_pushnumber(L, posX); + lua_pushnumber(L, posY); + lua_pushnumber(L, posZ); + + // push current floor surface (or nil) + if (pfloor && *pfloor) { + smlua_push_object(L, LOT_SURFACE, *pfloor, NULL); + } else { + lua_pushnil(L); + } + + // push current height + lua_pushnumber(L, *height); + + // call the callback (5 args, 2 results) + if (0 != smlua_call_hook(L, 5, 2, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_FLOOR]); + lua_settop(L, prevTop); + continue; + } + + bool override = false; + + // first return value: height (number) + if (lua_type(L, -2) == LUA_TNUMBER) { + *height = smlua_to_number(L, -2); + override = true; + } + + // second return value: surface (userdata) + if (lua_type(L, -1) == LUA_TUSERDATA) { + struct Surface *surface = (struct Surface *)smlua_to_cobject(L, -1, LOT_SURFACE); + if (surface && pfloor) { + *pfloor = surface; + override = true; + } + } + + lua_settop(L, prevTop); + if (override) { sInHook = false; return true; } + } + sInHook = false; + return false; +} + +bool smlua_call_event_hooks_HOOK_ON_FIND_SURFACE_ON_RAY(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_SURFACE_ON_RAY]; + 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 orig, dir + smlua_new_vec3f(orig); + smlua_new_vec3f(dir); + + // push hit_surface (or nil) + if (hit_surface && *hit_surface) { + smlua_push_object(L, LOT_SURFACE, *hit_surface, NULL); + } else { + lua_pushnil(L); + } + + // push hit_pos + smlua_new_vec3f(hit_pos); + + // call the callback (4 args, 2 results) + if (0 != smlua_call_hook(L, 4, 2, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_SURFACE_ON_RAY]); + lua_settop(L, prevTop); + continue; + } + + bool override = false; + + // first return value: surface (userdata) + if (lua_type(L, -2) == LUA_TUSERDATA) { + struct Surface *surface = (struct Surface *)smlua_to_cobject(L, -2, LOT_SURFACE); + if (surface && hit_surface) { + *hit_surface = surface; + override = true; + } + } + + // second return value: hitPos (table {x, y, z}) + if (lua_type(L, -1) == LUA_TTABLE) { + smlua_get_vec3f(hit_pos, -1); + override = true; + } + + lua_settop(L, prevTop); + if (override) { sInHook = false; return true; } + } + sInHook = false; + return false; +} + +bool smlua_call_event_hooks_HOOK_ON_FIND_WATER_LEVEL(f32 x, f32 z, f32 *waterLevel) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_WATER_LEVEL]; + 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 x, z + lua_pushnumber(L, x); + lua_pushnumber(L, z); + + // push current water level + lua_pushnumber(L, *waterLevel); + + // call the callback (3 args, 1 result) + if (0 != smlua_call_hook(L, 3, 1, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_WATER_LEVEL]); + lua_settop(L, prevTop); + continue; + } + + // return number overrides waterLevel + if (lua_type(L, -1) == LUA_TNUMBER) { + *waterLevel = smlua_to_number(L, -1); + lua_settop(L, prevTop); + sInHook = false; + return true; + } + + lua_settop(L, prevTop); + } + sInHook = false; + return false; +} + +bool smlua_call_event_hooks_HOOK_ON_FIND_POISON_GAS_LEVEL(f32 x, f32 z, f32 *gasLevel) { + static bool sInHook = false; + lua_State *L = gLuaState; + if (L == NULL || sInHook) { return false; } + sInHook = true; + + struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_FIND_POISON_GAS_LEVEL]; + 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 x, z + lua_pushnumber(L, x); + lua_pushnumber(L, z); + + // push current gas level + lua_pushnumber(L, *gasLevel); + + // call the callback (3 args, 1 result) + if (0 != smlua_call_hook(L, 3, 1, 0, hook->mod[i], hook->modFile[i])) { + LOG_LUA("Failed to call the callback for hook %s", sLuaHookedEventTypeName[HOOK_ON_FIND_POISON_GAS_LEVEL]); + lua_settop(L, prevTop); + continue; + } + + // return number overrides gasLevel + if (lua_type(L, -1) == LUA_TNUMBER) { + *gasLevel = smlua_to_number(L, -1); + lua_settop(L, prevTop); + sInHook = false; + return true; + } + + lua_settop(L, prevTop); + } + sInHook = false; + return false; +} + //////////////////// // hooked actions // //////////////////// diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index a857bbad3..c814c73e9 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -11,6 +11,8 @@ // forward declare struct Camera; struct WarpDest; +struct WallCollisionData; +struct Surface; // ! Hooks must be added at the end enum LuaHookedEventType { @@ -74,6 +76,12 @@ enum LuaHookedEventType { HOOK_ON_ADD_SURFACE, HOOK_ON_CLEAR_AREAS, HOOK_ON_PACKET_BYTESTRING_RECEIVE, + HOOK_ON_FIND_WALL_COLLISION, + HOOK_ON_FIND_CEIL, + HOOK_ON_FIND_FLOOR, + HOOK_ON_FIND_WATER_LEVEL, + HOOK_ON_FIND_POISON_GAS_LEVEL, + HOOK_ON_FIND_SURFACE_ON_RAY, HOOK_MAX, };