mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-05 01:38:07 +00:00
Add surface collision Lua hooks (#1139)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
* 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 <myster@d>
This commit is contained in:
parent
8fe56ab999
commit
2c367b556d
9 changed files with 368 additions and 6 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
-- ...
|
||||
|
|
|
|||
|
|
@ -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:](#)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 //
|
||||
////////////////////
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue