From 82444bc3bfd1aface3b4aeb9d35c3ce7b8228556 Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Thu, 19 Dec 2024 10:24:47 -0500
Subject: [PATCH 1/5] Add HOOK_HEALED_MARIO and HOOK_HURT_MARIO
---
autogen/convert_constants.py | 3 +-
autogen/lua_definitions/constants.lua | 30 ++++++++++++++++++-
autogen/lua_definitions/functions.lua | 5 ++++
docs/lua/constants.md | 27 ++++++++++++++++-
docs/lua/functions-3.md | 20 +++++++++++++
docs/lua/functions.md | 1 +
docs/lua/guides/hooks.md | 43 +++++++++++++++++++++------
src/game/mario.c | 17 +++++++++++
src/game/mario.h | 13 ++++++++
src/game/mario_actions_airborne.c | 20 ++-----------
src/game/mario_actions_moving.c | 9 +-----
src/pc/lua/smlua_constants_autogen.c | 10 ++++++-
src/pc/lua/smlua_functions_autogen.c | 18 +++++++++++
src/pc/lua/smlua_hooks.c | 2 +-
src/pc/lua/smlua_hooks.h | 4 +++
15 files changed, 182 insertions(+), 40 deletions(-)
diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py
index 629a9a815..86c168e6c 100644
--- a/autogen/convert_constants.py
+++ b/autogen/convert_constants.py
@@ -47,7 +47,8 @@
"src/pc/djui/djui_console.h",
"src/game/player_palette.h",
"src/pc/network/lag_compensation.h",
- "src/pc/djui/djui_panel_menu.h"
+ "src/pc/djui/djui_panel_menu.h",
+ "src/game/mario.h"
]
exclude_constants = {
diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index c5626f87c..282c55325 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -4143,6 +4143,28 @@ HUD_DISPLAY_NONE = 0x0000
--- @type HUDDisplayFlag
HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_COIN_COUNT | HUD_DISPLAY_FLAG_STAR_COUNT | HUD_DISPLAY_FLAG_CAMERA_AND_POWER | HUD_DISPLAY_FLAG_CAMERA | HUD_DISPLAY_FLAG_POWER | HUD_DISPLAY_FLAG_KEYS | HUD_DISPLAY_FLAG_UNKNOWN_0020
+--- @class MarioHealType
+
+--- @type MarioHealType
+HEAL_NORMAL = 0
+
+--- @type MarioHealType
+HEAL_WATER = 1
+
+--- @class MarioHurtType
+
+--- @type MarioHurtType
+HURT_NORMAL = 0
+
+--- @type MarioHurtType
+HURT_WATER = 1
+
+--- @type MarioHurtType
+HURT_TOXIC_GAS = 2
+
+--- @type MarioHurtType
+HURT_BURNING = 3
+
--- @class CharacterAnimID
--- @type CharacterAnimID
@@ -9158,7 +9180,13 @@ HOOK_ON_NAMETAGS_RENDER = 46
HOOK_ON_DJUI_THEME_CHANGED = 47
--- @type LuaHookedEventType
-HOOK_MAX = 48
+HOOK_HEALED_MARIO = 48
+
+--- @type LuaHookedEventType
+HOOK_HURT_MARIO = 49
+
+--- @type LuaHookedEventType
+HOOK_MAX = 50
--- @class LuaModMenuElementType
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 786e9d104..8db9b1adb 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -5081,6 +5081,11 @@ function transition_submerged_to_walking(m)
-- ...
end
+--- @param m MarioState
+function update_burning_health_common(m)
+ -- ...
+end
+
--- @param m MarioState
function update_mario_pos_for_anim(m)
-- ...
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index 3380e2253..3d596feaf 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -35,6 +35,9 @@
- [enum LevelNum](#enum-LevelNum)
- [level_update.h](#level_updateh)
- [enum HUDDisplayFlag](#enum-HUDDisplayFlag)
+- [mario.h](#marioh)
+ - [enum MarioHealType](#enum-MarioHealType)
+ - [enum MarioHurtType](#enum-MarioHurtType)
- [mario_animation_ids.h](#mario_animation_idsh)
- [enum CharacterAnimID](#enum-CharacterAnimID)
- [enum MarioAnimID](#enum-MarioAnimID)
@@ -1522,6 +1525,26 @@
+## [mario.h](#mario.h)
+
+### [enum MarioHealType](#MarioHealType)
+| Identifier | Value |
+| :--------- | :---- |
+| HEAL_NORMAL | 0 |
+| HEAL_WATER | 1 |
+
+### [enum MarioHurtType](#MarioHurtType)
+| Identifier | Value |
+| :--------- | :---- |
+| HURT_NORMAL | 0 |
+| HURT_WATER | 1 |
+| HURT_TOXIC_GAS | 2 |
+| HURT_BURNING | 3 |
+
+[:arrow_up_small:](#)
+
+
+
## [mario_animation_ids.h](#mario_animation_ids.h)
### [enum CharacterAnimID](#CharacterAnimID)
@@ -3335,7 +3358,9 @@
| HOOK_ON_MODS_LOADED | 45 |
| HOOK_ON_NAMETAGS_RENDER | 46 |
| HOOK_ON_DJUI_THEME_CHANGED | 47 |
-| HOOK_MAX | 48 |
+| HOOK_HEALED_MARIO | 48 |
+| HOOK_HURT_MARIO | 49 |
+| HOOK_MAX | 50 |
### [enum LuaModMenuElementType](#LuaModMenuElementType)
| Identifier | Value |
diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md
index 6589eb44c..29e16e8be 100644
--- a/docs/lua/functions-3.md
+++ b/docs/lua/functions-3.md
@@ -7090,6 +7090,26 @@ Creates a warp node in the current level and area with id `id` that goes to the
+## [update_burning_health_common](#update_burning_health_common)
+
+### Lua Example
+`update_burning_health_common(m)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| m | [MarioState](structs.md#MarioState) |
+
+### Returns
+- None
+
+### C Prototype
+`void update_burning_health_common(struct MarioState* m);`
+
+[:arrow_up_small:](#)
+
+
+
## [update_mario_pos_for_anim](#update_mario_pos_for_anim)
### Lua Example
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 878e1acbe..d29b3e6a1 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -992,6 +992,7 @@
- [set_steep_jump_action](functions-3.md#set_steep_jump_action)
- [set_water_plunge_action](functions-3.md#set_water_plunge_action)
- [transition_submerged_to_walking](functions-3.md#transition_submerged_to_walking)
+ - [update_burning_health_common](functions-3.md#update_burning_health_common)
- [update_mario_pos_for_anim](functions-3.md#update_mario_pos_for_anim)
- [update_mario_sound_and_camera](functions-3.md#update_mario_sound_and_camera)
diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md
index 8459e3795..121944326 100644
--- a/docs/lua/guides/hooks.md
+++ b/docs/lua/guides/hooks.md
@@ -4,15 +4,38 @@
Hooks are a way for SM64 to trigger Lua code, whereas the functions listed in [functions](../functions.md) allow Lua to trigger SM64 code.
# Supported Hooks
-- [hook_behavior](#hook_behavior)
-- [hook_chat_command](#hook_chat_command)
-- [hook_event](#hook_event)
-- [hook_mario_action](#hook_mario_action)
-- [hook_on_sync_table_change](#hook_on_sync_table_change)
-- [hook_mod_menu_button](#hook_mod_menu_button)
-- [hook_mod_menu_checkbox](#hook_mod_menu_checkbox)
-- [hook_mod_menu_slider](#hook_mod_menu_slider)
-- [hook_mod_menu_inputbox](#hook_mod_menu_inputbox)
+- [Hooks](#hooks)
+- [Supported Hooks](#supported-hooks)
+ - [hook\_behavior](#hook_behavior)
+ - [Parameters](#parameters)
+ - [Returns](#returns)
+ - [Lua Example](#lua-example)
+ - [hook\_chat\_command](#hook_chat_command)
+ - [Parameters](#parameters-1)
+ - [Lua Example](#lua-example-1)
+ - [hook\_event](#hook_event)
+ - [Hook Event Types](#hook-event-types)
+ - [Parameters](#parameters-2)
+ - [Lua Example](#lua-example-2)
+ - [hook\_mario\_action](#hook_mario_action)
+ - [Parameters](#parameters-3)
+ - [Action Hook Types](#action-hook-types)
+ - [Lua Example](#lua-example-3)
+ - [hook\_on\_sync\_table\_change](#hook_on_sync_table_change)
+ - [Parameters](#parameters-4)
+ - [Lua Example](#lua-example-4)
+ - [hook\_mod\_menu\_button](#hook_mod_menu_button)
+ - [Parameters](#parameters-5)
+ - [Lua Example](#lua-example-5)
+ - [hook\_mod\_menu\_checkbox](#hook_mod_menu_checkbox)
+ - [Parameters](#parameters-6)
+ - [Lua Example](#lua-example-6)
+ - [hook\_mod\_menu\_slider](#hook_mod_menu_slider)
+ - [Parameters](#parameters-7)
+ - [Lua Example](#lua-example-7)
+ - [hook\_mod\_menu\_inputbox](#hook_mod_menu_inputbox)
+ - [Parameters](#parameters-8)
+ - [Lua Example](#lua-example-8)
@@ -139,6 +162,8 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_MODS_LOADED | Called directly after every mod file is loaded in by smlua | None |
| HOOK_ON_NAMETAGS_RENDER | Called when nametags are rendered. Return a `string` to change what renders on the nametag, return an empty `string` to render nothing. | `string` playerIndex |
| HOOK_ON_DJUI_THEME_CHANGED | Called when the DJUI theme is changed. Run `djui_menu_get_theme()` to get the new theme. | None |
+| HOOK_HEALED_MARIO | Called when any player is about to heal from any source. Called once per affected player. | MarioState mario, `integer` healType |
+| HOOK_HURT_MARIO | Called when any player is about to take damage from any source. Called once per affected player. | MarioState mario, `integer` hurtType |
### Parameters
diff --git a/src/game/mario.c b/src/game/mario.c
index 06049177f..2d5aed604 100644
--- a/src/game/mario.c
+++ b/src/game/mario.c
@@ -1689,6 +1689,18 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
}
}
+void update_burning_health_common(struct MarioState* m) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_BURNING, NULL);
+ m->health -= 10;
+ if (m->health < 0x100) {
+ extern struct MarioState gMarioStates[];
+ if (m == &gMarioStates[0]) {
+ // never kill remote marios
+ set_mario_action(m, ACT_STANDING_DEATH, 0);
+ }
+ }
+}
+
/**
* Both increments and decrements Mario's HP.
*/
@@ -1701,6 +1713,7 @@ void update_mario_health(struct MarioState *m) {
if (((u32) m->healCounter | (u32) m->hurtCounter) == 0) {
if ((m->input & INPUT_IN_POISON_GAS) && !(m->action & ACT_FLAG_INTANGIBLE)) {
if (!(m->flags & MARIO_METAL_CAP) && !gDebugLevelSelect) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_TOXIC_GAS, NULL);
m->health -= 4;
}
} else {
@@ -1711,8 +1724,10 @@ void update_mario_health(struct MarioState *m) {
// when in snow terrains lose 3 health.
// If using the debug level select, do not lose any HP to water.
if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_WATER, NULL);
m->health += 0x1A;
} else if (!gDebugLevelSelect) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_WATER, NULL);
m->health -= (terrainIsSnow ? 3 : 1);
}
}
@@ -1720,10 +1735,12 @@ void update_mario_health(struct MarioState *m) {
}
if (m->healCounter > 0) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_NORMAL, NULL);
m->health += 0x40;
m->healCounter--;
}
if (m->hurtCounter > 0) {
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_NORMAL, NULL);
m->health -= 0x40;
m->hurtCounter--;
}
diff --git a/src/game/mario.h b/src/game/mario.h
index f0ff3d97f..c61b8f1fb 100644
--- a/src/game/mario.h
+++ b/src/game/mario.h
@@ -9,6 +9,18 @@
extern u16 gLocalBubbleCounter;
struct WallCollisionData;
+enum MarioHealType {
+ HEAL_NORMAL,
+ HEAL_WATER,
+};
+
+enum MarioHurtType {
+ HURT_NORMAL,
+ HURT_WATER,
+ HURT_TOXIC_GAS,
+ HURT_BURNING,
+};
+
s32 is_anim_at_end(struct MarioState *m);
s32 is_anim_past_end(struct MarioState *m);
s16 set_mario_animation(struct MarioState *m, s32 targetAnimID);
@@ -68,5 +80,6 @@ void init_mario_single_from_save_file(struct MarioState* m, u16 index);
void init_mario_from_save_file(void);
void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear);
void mario_update_wall(struct MarioState* m, struct WallCollisionData* wcd);
+void update_burning_health_common(struct MarioState* m);
#endif // MARIO_H
diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c
index 602727819..ae3a44860 100644
--- a/src/game/mario_actions_airborne.c
+++ b/src/game/mario_actions_airborne.c
@@ -1045,15 +1045,7 @@ s32 act_burning_jump(struct MarioState *m) {
m->marioObj->oMarioBurnTimer += 3;
- m->health -= 10;
- if (m->health < 0x100) {
- if (m != &gMarioStates[0]) {
- // never kill remote marios
- m->health = 0x100;
- } else {
- m->health = 0xFF;
- }
- }
+ update_burning_health_common(m);
reset_rumble_timers(m);
return FALSE;
@@ -1072,15 +1064,7 @@ s32 act_burning_fall(struct MarioState *m) {
set_mario_particle_flags(m, PARTICLE_FIRE, FALSE);
m->marioObj->oMarioBurnTimer += 3;
- m->health -= 10;
- if (m->health < 0x100) {
- if (m != &gMarioStates[0]) {
- // never kill remote marios
- m->health = 0x100;
- } else {
- m->health = 0xFF;
- }
- }
+ update_burning_health_common(m);
reset_rumble_timers(m);
return FALSE;
diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c
index c8add04f6..09f131e1f 100644
--- a/src/game/mario_actions_moving.c
+++ b/src/game/mario_actions_moving.c
@@ -1388,14 +1388,7 @@ s32 act_burning_ground(struct MarioState *m) {
set_mario_particle_flags(m, PARTICLE_FIRE, FALSE);
play_sound(SOUND_MOVING_LAVA_BURN, m->marioObj->header.gfx.cameraToObject);
- m->health -= 10;
- if (m->health < 0x100) {
- extern struct MarioState gMarioStates[];
- if (m == &gMarioStates[0]) {
- // never kill remote marios
- set_mario_action(m, ACT_STANDING_DEATH, 0);
- }
- }
+ update_burning_health_common(m);
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index d41e300bc..f58a55abc 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -1545,6 +1545,12 @@ char gSmluaConstants[] = ""
"HUD_DISPLAY_FLAG_EMPHASIZE_POWER = 0x8000\n"
"HUD_DISPLAY_NONE = 0x0000\n"
"HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_COIN_COUNT | HUD_DISPLAY_FLAG_STAR_COUNT | HUD_DISPLAY_FLAG_CAMERA_AND_POWER | HUD_DISPLAY_FLAG_CAMERA | HUD_DISPLAY_FLAG_POWER | HUD_DISPLAY_FLAG_KEYS | HUD_DISPLAY_FLAG_UNKNOWN_0020\n"
+"HEAL_NORMAL = 0\n"
+"HEAL_WATER = 1\n"
+"HURT_NORMAL = 0\n"
+"HURT_WATER = 1\n"
+"HURT_TOXIC_GAS = 2\n"
+"HURT_BURNING = 3\n"
"MARIO_ANIM_SLOW_LEDGE_GRAB = 0\n"
"MARIO_ANIM_FALL_OVER_BACKWARDS = 1\n"
"MARIO_ANIM_BACKWARD_AIR_KB = 2\n"
@@ -3202,7 +3208,9 @@ char gSmluaConstants[] = ""
"HOOK_ON_MODS_LOADED = 45\n"
"HOOK_ON_NAMETAGS_RENDER = 46\n"
"HOOK_ON_DJUI_THEME_CHANGED = 47\n"
-"HOOK_MAX = 48\n"
+"HOOK_HEALED_MARIO = 48\n"
+"HOOK_HURT_MARIO = 49\n"
+"HOOK_MAX = 50\n"
"ACTION_HOOK_EVERY_FRAME = 0\n"
"ACTION_HOOK_GRAVITY = 1\n"
"ACTION_HOOK_MAX = 2\n"
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index c3f3f02ae..2ab83ae4b 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -16045,6 +16045,23 @@ int smlua_func_transition_submerged_to_walking(lua_State* L) {
return 1;
}
+int smlua_func_update_burning_health_common(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", "update_burning_health_common", 1, top);
+ return 0;
+ }
+
+ struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "update_burning_health_common"); return 0; }
+
+ update_burning_health_common(m);
+
+ return 1;
+}
+
int smlua_func_update_mario_pos_for_anim(lua_State* L) {
if (L == NULL) { return 0; }
@@ -34490,6 +34507,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "set_steep_jump_action", smlua_func_set_steep_jump_action);
smlua_bind_function(L, "set_water_plunge_action", smlua_func_set_water_plunge_action);
smlua_bind_function(L, "transition_submerged_to_walking", smlua_func_transition_submerged_to_walking);
+ smlua_bind_function(L, "update_burning_health_common", smlua_func_update_burning_health_common);
smlua_bind_function(L, "update_mario_pos_for_anim", smlua_func_update_mario_pos_for_anim);
smlua_bind_function(L, "update_mario_sound_and_camera", smlua_func_update_mario_sound_and_camera);
//smlua_bind_function(L, "vec3f_find_ceil", smlua_func_vec3f_find_ceil); <--- UNIMPLEMENTED
diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c
index f0e834985..a7b3b4d56 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -910,7 +910,7 @@ void smlua_call_event_hooks_mario_param_and_int_ret_bool(enum LuaHookedEventType
}
// output the return value
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_type(L, -1) == LUA_TBOOLEAN && returnValue != NULL) {
*returnValue = smlua_to_boolean(L, -1);
}
lua_settop(L, prevTop);
diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h
index 5edeea0d5..5bce8721d 100644
--- a/src/pc/lua/smlua_hooks.h
+++ b/src/pc/lua/smlua_hooks.h
@@ -59,6 +59,8 @@ enum LuaHookedEventType {
HOOK_ON_MODS_LOADED,
HOOK_ON_NAMETAGS_RENDER,
HOOK_ON_DJUI_THEME_CHANGED,
+ HOOK_HEALED_MARIO,
+ HOOK_HURT_MARIO,
HOOK_MAX,
};
@@ -111,6 +113,8 @@ static const char* LuaHookedEventTypeName[] = {
"HOOK_ON_MODS_LOADED",
"HOOK_ON_NAMETAGS_RENDER",
"HOOK_ON_DJUI_THEME_CHANGED",
+ "HOOK_HEALED_MARIO",
+ "HOOK_HURT_MARIO"
"HOOK_MAX"
};
From 0cdd91592314cd053248018254a75f7d0d9a0628 Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Thu, 19 Dec 2024 10:32:41 -0500
Subject: [PATCH 2/5] Remove unnecessary line
---
src/game/mario.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/game/mario.c b/src/game/mario.c
index 2d5aed604..b2996fea6 100644
--- a/src/game/mario.c
+++ b/src/game/mario.c
@@ -1693,7 +1693,6 @@ void update_burning_health_common(struct MarioState* m) {
smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_BURNING, NULL);
m->health -= 10;
if (m->health < 0x100) {
- extern struct MarioState gMarioStates[];
if (m == &gMarioStates[0]) {
// never kill remote marios
set_mario_action(m, ACT_STANDING_DEATH, 0);
From edeb2d9dd71507a6b3a641aa4e25e0cd7a3eb7f9 Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Thu, 19 Dec 2024 10:49:25 -0500
Subject: [PATCH 3/5] Change when the hooks activate
I figured it would be more useful to hook after healing/taking damage rather than before
---
docs/lua/guides/hooks.md | 4 ++--
src/game/mario.c | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md
index 121944326..350adf882 100644
--- a/docs/lua/guides/hooks.md
+++ b/docs/lua/guides/hooks.md
@@ -162,8 +162,8 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_MODS_LOADED | Called directly after every mod file is loaded in by smlua | None |
| HOOK_ON_NAMETAGS_RENDER | Called when nametags are rendered. Return a `string` to change what renders on the nametag, return an empty `string` to render nothing. | `string` playerIndex |
| HOOK_ON_DJUI_THEME_CHANGED | Called when the DJUI theme is changed. Run `djui_menu_get_theme()` to get the new theme. | None |
-| HOOK_HEALED_MARIO | Called when any player is about to heal from any source. Called once per affected player. | MarioState mario, `integer` healType |
-| HOOK_HURT_MARIO | Called when any player is about to take damage from any source. Called once per affected player. | MarioState mario, `integer` hurtType |
+| HOOK_HEALED_MARIO | Called when any player has just healed from any source. Called once per affected player. | MarioState mario, `integer` healType |
+| HOOK_HURT_MARIO | Called when any player has just taken damage from any source. Called once per affected player. | MarioState mario, `integer` hurtType |
### Parameters
diff --git a/src/game/mario.c b/src/game/mario.c
index b2996fea6..b06f0493b 100644
--- a/src/game/mario.c
+++ b/src/game/mario.c
@@ -1690,8 +1690,8 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
}
void update_burning_health_common(struct MarioState* m) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_BURNING, NULL);
m->health -= 10;
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_BURNING, NULL);
if (m->health < 0x100) {
if (m == &gMarioStates[0]) {
// never kill remote marios
@@ -1712,8 +1712,8 @@ void update_mario_health(struct MarioState *m) {
if (((u32) m->healCounter | (u32) m->hurtCounter) == 0) {
if ((m->input & INPUT_IN_POISON_GAS) && !(m->action & ACT_FLAG_INTANGIBLE)) {
if (!(m->flags & MARIO_METAL_CAP) && !gDebugLevelSelect) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_TOXIC_GAS, NULL);
m->health -= 4;
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_TOXIC_GAS, NULL);
}
} else {
if ((m->action & ACT_FLAG_SWIMMING) && !(m->action & ACT_FLAG_INTANGIBLE)) {
@@ -1723,25 +1723,25 @@ void update_mario_health(struct MarioState *m) {
// when in snow terrains lose 3 health.
// If using the debug level select, do not lose any HP to water.
if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_WATER, NULL);
m->health += 0x1A;
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_WATER, NULL);
} else if (!gDebugLevelSelect) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_WATER, NULL);
m->health -= (terrainIsSnow ? 3 : 1);
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_WATER, NULL);
}
}
}
}
if (m->healCounter > 0) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_NORMAL, NULL);
m->health += 0x40;
m->healCounter--;
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HEALED_MARIO, m, HEAL_NORMAL, NULL);
}
if (m->hurtCounter > 0) {
- smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_NORMAL, NULL);
m->health -= 0x40;
m->hurtCounter--;
+ smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_HURT_MARIO, m, HURT_NORMAL, NULL);
}
if (m->health > 0x880) {
From 3d2fc6d464b86b44498b42b1ca9ebbf4b2786063 Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Sun, 19 Jan 2025 04:49:13 -0500
Subject: [PATCH 4/5] Complete merge
---
autogen/lua_definitions/structs.lua | 1 +
docs/lua/functions-4.md | 20 ++++++++++++++++++++
docs/lua/structs.md | 1 +
src/pc/lua/smlua_cobject_autogen.c | 3 ++-
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua
index f0d30015d..abbd2cbdd 100644
--- a/autogen/lua_definitions/structs.lua
+++ b/autogen/lua_definitions/structs.lua
@@ -1111,6 +1111,7 @@
--- @field public lightingDirX number
--- @field public lightingDirY number
--- @field public lightingDirZ number
+--- @field public mirrorMario boolean
--- @field public modelState integer
--- @field public punchState integer
--- @field public shadeB integer
diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md
index d82abe843..591d4dc9c 100644
--- a/docs/lua/functions-4.md
+++ b/docs/lua/functions-4.md
@@ -1207,6 +1207,26 @@ Transitions Mario from being underwater to a walking state. Resets camera to the
+## [update_burning_health_common](#update_burning_health_common)
+
+### Lua Example
+`update_burning_health_common(m)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| m | [MarioState](structs.md#MarioState) |
+
+### Returns
+- None
+
+### C Prototype
+`void update_burning_health_common(struct MarioState* m);`
+
+[:arrow_up_small:](#)
+
+
+
## [update_mario_pos_for_anim](#update_mario_pos_for_anim)
### Description
diff --git a/docs/lua/structs.md b/docs/lua/structs.md
index 7c186f093..b1fa4ac26 100644
--- a/docs/lua/structs.md
+++ b/docs/lua/structs.md
@@ -1694,6 +1694,7 @@
| lightingDirX | `number` | |
| lightingDirY | `number` | |
| lightingDirZ | `number` | |
+| mirrorMario | `boolean` | |
| modelState | `integer` | |
| punchState | `integer` | |
| shadeB | `integer` | |
diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c
index 6bb7e3349..6a69f0080 100644
--- a/src/pc/lua/smlua_cobject_autogen.c
+++ b/src/pc/lua/smlua_cobject_autogen.c
@@ -1391,7 +1391,7 @@ static struct LuaObjectField sMarioAnimationFields[LUA_MARIO_ANIMATION_FIELD_COU
{ "targetAnim", LVT_COBJECT_P, offsetof(struct MarioAnimation, targetAnim), false, LOT_ANIMATION },
};
-#define LUA_MARIO_BODY_STATE_FIELD_COUNT 25
+#define LUA_MARIO_BODY_STATE_FIELD_COUNT 26
static struct LuaObjectField sMarioBodyStateFields[LUA_MARIO_BODY_STATE_FIELD_COUNT] = {
{ "action", LVT_U32, offsetof(struct MarioBodyState, action), false, LOT_NONE },
{ "allowPartRotation", LVT_U8, offsetof(struct MarioBodyState, allowPartRotation), false, LOT_NONE },
@@ -1409,6 +1409,7 @@ static struct LuaObjectField sMarioBodyStateFields[LUA_MARIO_BODY_STATE_FIELD_CO
{ "lightingDirX", LVT_F32, offsetof(struct MarioBodyState, lightingDirX), false, LOT_NONE },
{ "lightingDirY", LVT_F32, offsetof(struct MarioBodyState, lightingDirY), false, LOT_NONE },
{ "lightingDirZ", LVT_F32, offsetof(struct MarioBodyState, lightingDirZ), false, LOT_NONE },
+ { "mirrorMario", LVT_BOOL, offsetof(struct MarioBodyState, mirrorMario), false, LOT_NONE },
{ "modelState", LVT_S16, offsetof(struct MarioBodyState, modelState), false, LOT_NONE },
{ "punchState", LVT_U8, offsetof(struct MarioBodyState, punchState), false, LOT_NONE },
{ "shadeB", LVT_U16, offsetof(struct MarioBodyState, shadeB), false, LOT_NONE },
From 523a288e262dff7a0be125517ab76e4d8f579dae Mon Sep 17 00:00:00 2001
From: Sunk <69110309+Sunketchupm@users.noreply.github.com>
Date: Thu, 20 Feb 2025 11:13:25 -0500
Subject: [PATCH 5/5] Add HOOK_AFTER_QUARTER_STEP
---
autogen/lua_definitions/constants.lua | 7 ++++--
docs/lua/constants.md | 3 ++-
docs/lua/guides/hooks.md | 1 +
src/game/mario_actions_automatic.c | 33 ++++++++++--------------
src/game/mario_actions_submerged.c | 4 ++-
src/game/mario_step.c | 6 ++++-
src/pc/lua/smlua_constants_autogen.c | 3 ++-
src/pc/lua/smlua_hooks.c | 36 +++++++++++++++++++++++++++
src/pc/lua/smlua_hooks.h | 3 +++
9 files changed, 70 insertions(+), 26 deletions(-)
diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index f560733f2..87a0c0106 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -9221,7 +9221,10 @@ HOOK_HURT_MARIO = 53
HOOK_ON_INTERACTIONS = 54
--- @type LuaHookedEventType
-HOOK_MAX = 55
+HOOK_AFTER_QUARTER_STEP = 55
+
+--- @type LuaHookedEventType
+HOOK_MAX = 56
--- @class LuaModMenuElementType
@@ -12554,7 +12557,7 @@ MINOR_VERSION_NUMBER = 1
SM64COOPDX_VERSION = "v1.2.1"
--- @type integer
-VERSION_NUMBER = 38
+VERSION_NUMBER = 39
--- @type string
VERSION_TEXT = "v"
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index 46df7f667..c13b957eb 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -3376,7 +3376,8 @@
| HOOK_HEALED_MARIO | 52 |
| HOOK_HURT_MARIO | 53 |
| HOOK_ON_INTERACTIONS | 54 |
-| HOOK_MAX | 55 |
+| HOOK_AFTER_QUARTER_STEP | 55 |
+| HOOK_MAX | 56 |
### [enum LuaModMenuElementType](#LuaModMenuElementType)
| Identifier | Value |
diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md
index 8f0d08f0b..d1cf809b0 100644
--- a/docs/lua/guides/hooks.md
+++ b/docs/lua/guides/hooks.md
@@ -168,6 +168,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_HEALED_MARIO | Called when any player has just healed from any source. Called once per affected player. | MarioState mario, `integer` healType |
| HOOK_HURT_MARIO | Called when any player has just taken damage from any source. Called once per affected player. | MarioState mario, `integer` hurtType |
| HOOK_ON_INTERACTIONS | Called when the Mario interactions are processed | [MarioState](../structs.md#MarioState) mario |
+| HOOK_AFTER_QUARTER_STEP | Called after a single quarter step has been processed. Return a step result to override the current step result. | [MarioState](../structs.md#MarioState) mario, `integer` stepType, `integer` stepResult, `integer` stepNumber |
### Parameters
diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c
index 355957bfa..983c69c4c 100644
--- a/src/game/mario_actions_automatic.c
+++ b/src/game/mario_actions_automatic.c
@@ -365,26 +365,19 @@ s32 perform_hanging_step(struct MarioState *m, Vec3f nextPos) {
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
ceilHeight = vec3f_mario_ceil(nextPos, floorHeight, &ceil);
- if (floor == NULL) {
- return HANG_HIT_CEIL_OR_OOB;
- }
- if (ceil == NULL) {
- return HANG_LEFT_CEIL;
- }
- if (ceilHeight - floorHeight <= 160.0f) {
- return HANG_HIT_CEIL_OR_OOB;
- }
- if (ceil->type != SURFACE_HANGABLE) {
- return HANG_LEFT_CEIL;
- }
-
- ceilOffset = ceilHeight - (nextPos[1] + 160.0f);
- if (ceilOffset < -30.0f) {
- return HANG_HIT_CEIL_OR_OOB;
- }
- if (ceilOffset > 30.0f) {
- return HANG_LEFT_CEIL;
- }
+ s32 stepResult = HANG_NONE;
+ if (floor == NULL) { stepResult = HANG_HIT_CEIL_OR_OOB; }
+ else if (ceil == NULL) { stepResult = HANG_LEFT_CEIL; }
+ else if (ceilHeight - floorHeight <= 160.0f) { stepResult = HANG_HIT_CEIL_OR_OOB; }
+ else if (ceil->type != SURFACE_HANGABLE) { stepResult = HANG_LEFT_CEIL; }
+ else {
+ ceilOffset = ceilHeight - (nextPos[1] + 160.0f);
+ if (ceilOffset < -30.0f) { stepResult = HANG_HIT_CEIL_OR_OOB; }
+ if (ceilOffset > 30.0f) { stepResult = HANG_LEFT_CEIL; }
+ }
+
+ smlua_call_event_hooks_after_quarter_step(HOOK_AFTER_QUARTER_STEP, m, STEP_TYPE_HANG, stepResult, 0, &stepResult);
+ if (stepResult != HANG_NONE) { return stepResult; }
nextPos[1] = m->ceilHeight - 160.0f;
vec3f_copy(m->pos, nextPos);
diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c
index 54468b5bc..90aa35616 100644
--- a/src/game/mario_actions_submerged.c
+++ b/src/game/mario_actions_submerged.c
@@ -186,7 +186,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) {
u32 perform_water_step(struct MarioState *m) {
if (!m) { return 0; }
UNUSED u32 unused;
- u32 stepResult;
+ s32 stepResult;
Vec3f nextPos;
Vec3f step;
struct Object *marioObj = m->marioObj;
@@ -211,6 +211,8 @@ u32 perform_water_step(struct MarioState *m) {
stepResult = perform_water_full_step(m, nextPos);
+ smlua_call_event_hooks_after_quarter_step(HOOK_AFTER_QUARTER_STEP, m, STEP_TYPE_WATER, stepResult, 0, &stepResult);
+
vec3f_copy(marioObj->header.gfx.pos, m->pos);
vec3s_set(marioObj->header.gfx.angle, -m->faceAngle[0], m->faceAngle[1], m->faceAngle[2]);
diff --git a/src/game/mario_step.c b/src/game/mario_step.c
index 6ac8d33bb..6431aa908 100644
--- a/src/game/mario_step.c
+++ b/src/game/mario_step.c
@@ -353,7 +353,7 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
s32 perform_ground_step(struct MarioState *m) {
if (!m) { return 0; }
s32 i;
- u32 stepResult;
+ s32 stepResult;
Vec3f intendedPos;
s32 returnValue = 0;
@@ -382,6 +382,8 @@ s32 perform_ground_step(struct MarioState *m) {
stepResult = perform_ground_quarter_step(m, intendedPos);
gFindWallDirectionActive = false;
+ smlua_call_event_hooks_after_quarter_step(HOOK_AFTER_QUARTER_STEP, m, STEP_TYPE_GROUND, stepResult, i, &stepResult);
+
if (stepResult == GROUND_STEP_LEFT_GROUND || stepResult == GROUND_STEP_HIT_WALL_STOP_QSTEPS) {
break;
}
@@ -753,6 +755,8 @@ s32 perform_air_step(struct MarioState *m, u32 stepArg) {
gFindWallDirectionAirborne = false;
gFindWallDirectionActive = false;
+ smlua_call_event_hooks_after_quarter_step(HOOK_AFTER_QUARTER_STEP, m, STEP_TYPE_AIR, quarterStepResult, i, &quarterStepResult);
+
//! On one qf, hit OOB/ceil/wall to store the 2 return value, and continue
// getting 0s until your last qf. Graze a wall on your last qf, and it will
// return the stored 2 with a sharply angled reference wall. (some gwks)
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index c9ca2ab74..4f5893c58 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -3221,7 +3221,8 @@ char gSmluaConstants[] = ""
"HOOK_HEALED_MARIO = 52\n"
"HOOK_HURT_MARIO = 53\n"
"HOOK_ON_INTERACTIONS = 54\n"
-"HOOK_MAX = 55\n"
+"HOOK_AFTER_QUARTER_STEP = 55\n"
+"HOOK_MAX = 56\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 653ab183e..82911154e 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -1127,6 +1127,42 @@ void smlua_call_event_hooks_string_param(enum LuaHookedEventType hookType, const
}
}
+void smlua_call_event_hooks_after_quarter_step(enum LuaHookedEventType hookType, struct MarioState* m, s32 stepType, s32 stepResult, s32 stepNumber, s32* newResult) {
+ 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 mario state
+ lua_getglobal(L, "gMarioStates");
+ lua_pushinteger(L, m->playerIndex);
+ lua_gettable(L, -2);
+ lua_remove(L, -2);
+
+ // push params
+ lua_pushinteger(L, stepType);
+ lua_pushinteger(L, stepResult);
+ lua_pushinteger(L, stepNumber);
+
+ // call the callback
+ if (0 != smlua_call_hook(L, 4, 1, 0, hook->mod[i])) {
+ LOG_LUA("Failed to call the callback: %u", hookType);
+ continue;
+ }
+
+ // output the return value
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ *newResult = smlua_to_integer(L, -1);
+ lua_settop(L, prevTop);
+ }
+ lua_settop(L, prevTop);
+ }
+}
+
////////////////////
// hooked actions //
////////////////////
diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h
index 2e47fb4e1..9e0bf5615 100644
--- a/src/pc/lua/smlua_hooks.h
+++ b/src/pc/lua/smlua_hooks.h
@@ -67,6 +67,7 @@ enum LuaHookedEventType {
HOOK_HEALED_MARIO,
HOOK_HURT_MARIO,
HOOK_ON_INTERACTIONS,
+ HOOK_AFTER_QUARTER_STEP,
HOOK_MAX,
};
@@ -126,6 +127,7 @@ static const char* LuaHookedEventTypeName[] = {
"HOOK_HEALED_MARIO",
"HOOK_HURT_MARIO",
"HOOK_ON_INTERACTIONS",
+ "HOOK_AFTER_QUARTER_STEP",
"HOOK_MAX"
};
@@ -206,6 +208,7 @@ void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hoo
void smlua_call_event_hooks_on_seq_load(enum LuaHookedEventType hookType, u32 player, u32 seqId, s32 loadAsync, s16* returnValue);
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);
+void smlua_call_event_hooks_after_quarter_step(enum LuaHookedEventType hookType, struct MarioState* m, s32 stepType, s32 stepResult, s32 stepNumber, s32* newResult);
enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior);
const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior);