From 9acb632b8ec9fd6aba212c1b272ba91be29c3ea9 Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Tue, 24 Jun 2025 16:15:27 -0400
Subject: [PATCH] Fix HOOK_ALLOW_HAZARD_SURFACE and expose `SURFACE_IS_*`
macros (#865)
* Fix HOOK_ALLOW_HAZARD_SURFACE
* Peachy's suggestions
* Exposed `surface_is_*` macros
---
autogen/lua_definitions/functions.lua | 21 ++++++++
docs/lua/functions-6.md | 69 ++++++++++++++++++++++++
docs/lua/functions.md | 3 ++
include/surface_terrains.h | 2 +-
src/game/interaction.c | 8 +--
src/game/mario_actions_airborne.c | 12 ++---
src/game/mario_step.c | 33 ++++++++----
src/pc/lua/smlua_functions_autogen.c | 54 +++++++++++++++++++
src/pc/lua/utils/smlua_collision_utils.c | 15 ++++++
src/pc/lua/utils/smlua_collision_utils.h | 7 +++
10 files changed, 203 insertions(+), 21 deletions(-)
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index ce8adeb06..c0b532b10 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -10223,6 +10223,27 @@ function smlua_collision_util_find_surface_types(data)
-- ...
end
+--- @param surf Surface
+--- @return boolean
+--- Checks if the surface is quicksand
+function surface_is_quicksand(surf)
+ -- ...
+end
+
+--- @param surf Surface
+--- @return boolean
+--- Checks if the surface is not a hard surface
+function surface_is_not_hard(surf)
+ -- ...
+end
+
+--- @param surf Surface
+--- @return boolean
+--- Checks if the surface is a painting warp
+function surface_is_painting_warp(surf)
+ -- ...
+end
+
--- @param fov number
--- Sets the override FOV
function set_override_fov(fov)
diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md
index c87745a38..46f2aef50 100644
--- a/docs/lua/functions-6.md
+++ b/docs/lua/functions-6.md
@@ -2112,6 +2112,75 @@ Gets a table of the surface types from `data`
+## [surface_is_quicksand](#surface_is_quicksand)
+
+### Description
+Checks if the surface is quicksand
+
+### Lua Example
+`local booleanValue = surface_is_quicksand(surf)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| surf | [Surface](structs.md#Surface) |
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool surface_is_quicksand(struct Surface* surf);`
+
+[:arrow_up_small:](#)
+
+
+
+## [surface_is_not_hard](#surface_is_not_hard)
+
+### Description
+Checks if the surface is not a hard surface
+
+### Lua Example
+`local booleanValue = surface_is_not_hard(surf)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| surf | [Surface](structs.md#Surface) |
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool surface_is_not_hard(struct Surface* surf);`
+
+[:arrow_up_small:](#)
+
+
+
+## [surface_is_painting_warp](#surface_is_painting_warp)
+
+### Description
+Checks if the surface is a painting warp
+
+### Lua Example
+`local booleanValue = surface_is_painting_warp(surf)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| surf | [Surface](structs.md#Surface) |
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool surface_is_painting_warp(struct Surface* surf);`
+
+[:arrow_up_small:](#)
+
+
+
---
# functions from smlua_deprecated.h
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 10d832f15..bbef2c349 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1843,6 +1843,9 @@
- [smlua_collision_util_get_current_terrain_collision](functions-6.md#smlua_collision_util_get_current_terrain_collision)
- [smlua_collision_util_get_level_collision](functions-6.md#smlua_collision_util_get_level_collision)
- [smlua_collision_util_find_surface_types](functions-6.md#smlua_collision_util_find_surface_types)
+ - [surface_is_quicksand](functions-6.md#surface_is_quicksand)
+ - [surface_is_not_hard](functions-6.md#surface_is_not_hard)
+ - [surface_is_painting_warp](functions-6.md#surface_is_painting_warp)
diff --git a/include/surface_terrains.h b/include/surface_terrains.h
index d020cd45c..091ed64d4 100644
--- a/include/surface_terrains.h
+++ b/include/surface_terrains.h
@@ -151,7 +151,7 @@
#define SURFACE_WOBBLING_WARP 0x00FD // Pool warp (HMC & DDD)
#define SURFACE_TRAPDOOR 0x00FF // Bowser Left trapdoor, has no action defined
-#define SURFACE_IS_QUICKSAND(cmd) (cmd >= 0x21 && cmd < 0x28) // Doesn't include SURFACE_INSTANT_MOVING_QUICKSAND
+#define SURFACE_IS_QUICKSAND(cmd) ((cmd >= 0x21 && cmd < 0x28) || cmd == SURFACE_INSTANT_MOVING_QUICKSAND)
#define SURFACE_IS_NOT_HARD(cmd) (cmd != SURFACE_HARD && \
!(cmd >= 0x35 && cmd <= 0x37))
#define SURFACE_IS_PAINTING_WARP(cmd) (cmd >= 0xD3 && cmd < 0xFD)
diff --git a/src/game/interaction.c b/src/game/interaction.c
index 3ea2ef1bd..9c963673c 100644
--- a/src/game/interaction.c
+++ b/src/game/interaction.c
@@ -2460,10 +2460,12 @@ void check_death_barrier(struct MarioState *m) {
void check_lava_boost(struct MarioState *m) {
if (!m) { return; }
- bool allowHazard = true;
- smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_FLOOR, &allowHazard);
- if (m->action == ACT_BUBBLED || (!allowHazard)) { return; }
+ if (m->action == ACT_BUBBLED) { return; }
if (!(m->action & ACT_FLAG_RIDING_SHELL) && m->pos[1] < m->floorHeight + 10.0f) {
+ bool allowHazard = true;
+ smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_FLOOR, &allowHazard);
+ if (!allowHazard) { return; }
+
if (!(m->flags & MARIO_METAL_CAP)) {
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 12 : 18;
}
diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c
index 1865d465c..8c368a4ea 100644
--- a/src/game/mario_actions_airborne.c
+++ b/src/game/mario_actions_airborne.c
@@ -206,16 +206,16 @@ s32 check_horizontal_wind(struct MarioState *m) {
struct Surface *floor;
f32 speed;
s16 pushAngle;
- bool allowHazard = true;
- smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_HORIZONTAL_WIND, &allowHazard);
- if (!allowHazard) {
- return FALSE;
- }
floor = m->floor;
-
if (floor && floor->type == SURFACE_HORIZONTAL_WIND) {
+ bool allowHazard = true;
+ smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_HORIZONTAL_WIND, &allowHazard);
+ if (!allowHazard) {
+ return FALSE;
+ }
+
pushAngle = floor->force << 8;
m->slideVelX += 1.2f * sins(pushAngle);
diff --git a/src/game/mario_step.c b/src/game/mario_step.c
index 16be3e767..5f8a84145 100644
--- a/src/game/mario_step.c
+++ b/src/game/mario_step.c
@@ -123,10 +123,8 @@ void mario_bonk_reflection(struct MarioState *m, u8 negateSpeed) {
u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
if (!m) { return 0; }
- bool allowHazard = true;
- smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_QUICKSAND, &allowHazard);
extern bool gDjuiInMainMenu;
- if (m->action & ACT_FLAG_RIDING_SHELL || (!allowHazard) || gDjuiInMainMenu) {
+ if (m->action & ACT_FLAG_RIDING_SHELL || gDjuiInMainMenu) {
m->quicksandDepth = 0.0f;
} else {
if (m->quicksandDepth < 1.1f) {
@@ -135,6 +133,16 @@ u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
u32 floorType = m->floor ? m->floor->type : SURFACE_DEFAULT;
+ // Only run the hook if the player is actually on quicksand
+ if (SURFACE_IS_QUICKSAND(floorType)) {
+ bool allowHazard = true;
+ smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_QUICKSAND, &allowHazard);
+ if (!allowHazard) {
+ m->quicksandDepth = 0;
+ return FALSE;
+ }
+ }
+
switch (floorType) {
case SURFACE_SHALLOW_QUICKSAND:
if ((m->quicksandDepth += sinkingSpeed) >= 10.0f) {
@@ -217,14 +225,15 @@ u32 mario_update_windy_ground(struct MarioState *m) {
if (!m) { return 0; }
struct Surface *floor = m->floor;
if (!floor) { return 0; }
- bool allowHazard = true;
- smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_HORIZONTAL_WIND, &allowHazard);
- if (!allowHazard) {
- return FALSE;
- }
extern bool gDjuiInMainMenu;
if (floor->type == SURFACE_HORIZONTAL_WIND && !gDjuiInMainMenu) {
+ bool allowHazard = true;
+ smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_HORIZONTAL_WIND, &allowHazard);
+ if (!allowHazard) {
+ return FALSE;
+ }
+
f32 pushSpeed;
s16 pushAngle = floor->force << 8;
@@ -721,12 +730,14 @@ void apply_vertical_wind(struct MarioState *m) {
if (!m) { return; }
f32 maxVelY;
f32 offsetY;
- bool allowHazard = true;
- smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_VERTICAL_WIND, &allowHazard);
- if (m->action != ACT_GROUND_POUND && allowHazard) {
+ if (m->action != ACT_GROUND_POUND) {
offsetY = m->pos[1] - -1500.0f;
if (m->floor && m->floor->type == SURFACE_VERTICAL_WIND && -3000.0f < offsetY && offsetY < 2000.0f) {
+ bool allowHazard = true;
+ smlua_call_event_hooks(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_VERTICAL_WIND, &allowHazard);
+ if (!allowHazard) { return; }
+
if (offsetY >= 0.0f) {
maxVelY = 10000.0f / (offsetY + 200.0f);
} else {
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 2bf3ba87c..16f3e16d5 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -30898,6 +30898,57 @@ int smlua_func_smlua_collision_util_find_surface_types(lua_State* L) {
return 1;
}
+int smlua_func_surface_is_quicksand(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 1) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "surface_is_quicksand", 1, top);
+ return 0;
+ }
+
+ struct Surface* surf = (struct Surface*)smlua_to_cobject(L, 1, LOT_SURFACE);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "surface_is_quicksand"); return 0; }
+
+ lua_pushboolean(L, surface_is_quicksand(surf));
+
+ return 1;
+}
+
+int smlua_func_surface_is_not_hard(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 1) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "surface_is_not_hard", 1, top);
+ return 0;
+ }
+
+ struct Surface* surf = (struct Surface*)smlua_to_cobject(L, 1, LOT_SURFACE);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "surface_is_not_hard"); return 0; }
+
+ lua_pushboolean(L, surface_is_not_hard(surf));
+
+ return 1;
+}
+
+int smlua_func_surface_is_painting_warp(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 1) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "surface_is_painting_warp", 1, top);
+ return 0;
+ }
+
+ struct Surface* surf = (struct Surface*)smlua_to_cobject(L, 1, LOT_SURFACE);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "surface_is_painting_warp"); return 0; }
+
+ lua_pushboolean(L, surface_is_painting_warp(surf));
+
+ return 1;
+}
+
////////////////////////
// smlua_deprecated.h //
////////////////////////
@@ -37033,6 +37084,9 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "smlua_collision_util_get_current_terrain_collision", smlua_func_smlua_collision_util_get_current_terrain_collision);
smlua_bind_function(L, "smlua_collision_util_get_level_collision", smlua_func_smlua_collision_util_get_level_collision);
smlua_bind_function(L, "smlua_collision_util_find_surface_types", smlua_func_smlua_collision_util_find_surface_types);
+ smlua_bind_function(L, "surface_is_quicksand", smlua_func_surface_is_quicksand);
+ smlua_bind_function(L, "surface_is_not_hard", smlua_func_surface_is_not_hard);
+ smlua_bind_function(L, "surface_is_painting_warp", smlua_func_surface_is_painting_warp);
// smlua_deprecated.h
smlua_bind_function(L, "djui_hud_set_render_behind_hud", smlua_func_djui_hud_set_render_behind_hud);
diff --git a/src/pc/lua/utils/smlua_collision_utils.c b/src/pc/lua/utils/smlua_collision_utils.c
index 7e9bafb0f..0a83bc172 100644
--- a/src/pc/lua/utils/smlua_collision_utils.c
+++ b/src/pc/lua/utils/smlua_collision_utils.c
@@ -237,3 +237,18 @@ void smlua_collision_util_find_surface_types(Collision* data) {
// Couldn't find anything
lua_pushnil(L);
}
+
+bool surface_is_quicksand(struct Surface* surf) {
+ if (surf == NULL) { return FALSE; }
+ return SURFACE_IS_QUICKSAND(surf->type);
+}
+
+bool surface_is_not_hard(struct Surface* surf) {
+ if (surf == NULL) { return FALSE; }
+ return SURFACE_IS_NOT_HARD(surf->type);
+}
+
+bool surface_is_painting_warp(struct Surface* surf) {
+ if (surf == NULL) { return FALSE; }
+ return SURFACE_IS_PAINTING_WARP(surf->type);
+}
\ No newline at end of file
diff --git a/src/pc/lua/utils/smlua_collision_utils.h b/src/pc/lua/utils/smlua_collision_utils.h
index 8782fc37e..8836a7162 100644
--- a/src/pc/lua/utils/smlua_collision_utils.h
+++ b/src/pc/lua/utils/smlua_collision_utils.h
@@ -142,4 +142,11 @@ Collision *smlua_collision_util_get_level_collision(u32 level, u16 area);
/* |description|Gets a table of the surface types from `data`|descriptionEnd| */
void smlua_collision_util_find_surface_types(Collision* data);
+/* |description|Checks if the surface is quicksand|descriptionEnd| */
+bool surface_is_quicksand(struct Surface* surf);
+/* |description|Checks if the surface is not a hard surface|descriptionEnd| */
+bool surface_is_not_hard(struct Surface* surf);
+/* |description|Checks if the surface is a painting warp|descriptionEnd| */
+bool surface_is_painting_warp(struct Surface* surf);
+
#endif