diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 5689b38d..d3f0d036 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -78,7 +78,7 @@ override_allowed_functions = { "src/game/level_update.h": [ "level_trigger_warp", "get_painting_warp_node", "initiate_painting_warp", "warp_special", "lvl_set_current_level", "level_control_timer_running" ], "src/game/area.h": [ "area_get_warp_node" ], "src/engine/level_script.h": [ "area_create_warp_node" ], - "src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color" ] + "src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color", "set_menu_mode", "create_dialog_box", "create_dialog_box_with_var", "create_dialog_inverted_box", "create_dialog_box_with_response", "reset_dialog_render_state", "close_dialog_box", ] } override_disallowed_functions = { diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 9c8c4b03..2ad745ee 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -4022,6 +4022,31 @@ function set_first_person_enabled(enable) -- ... end +--- @param dialog integer +--- @return nil +function create_dialog_box(dialog) + -- ... +end + +--- @param dialog integer +--- @return nil +function create_dialog_box_with_response(dialog) + -- ... +end + +--- @param dialog integer +--- @param dialogVar integer +--- @return nil +function create_dialog_box_with_var(dialog, dialogVar) + -- ... +end + +--- @param dialog integer +--- @return nil +function create_dialog_inverted_box(dialog) + -- ... +end + --- @return nil function reset_dialog_override_color() -- ... @@ -4032,6 +4057,11 @@ function reset_dialog_override_pos() -- ... end +--- @return nil +function reset_dialog_render_state() + -- ... +end + --- @param bgR integer --- @param bgG integer --- @param bgB integer @@ -4052,6 +4082,12 @@ function set_dialog_override_pos(x, y) -- ... end +--- @param mode integer +--- @return nil +function set_menu_mode(mode) + -- ... +end + --- @param width integer --- @return nil function set_min_dialog_width(width) @@ -8943,6 +8979,11 @@ function get_dialog_id() -- ... end +--- @return integer +function get_dialog_response() + -- ... +end + --- @return integer function get_envfx() -- ... diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md index aedf9eb5..371ec0b0 100644 --- a/docs/lua/functions-3.md +++ b/docs/lua/functions-3.md @@ -3348,6 +3348,87 @@
+## [create_dialog_box](#create_dialog_box) + +### Lua Example +`create_dialog_box(dialog)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dialog | `integer` | + +### Returns +- None + +### C Prototype +`void create_dialog_box(s16 dialog);` + +[:arrow_up_small:](#) + +
+ +## [create_dialog_box_with_response](#create_dialog_box_with_response) + +### Lua Example +`create_dialog_box_with_response(dialog)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dialog | `integer` | + +### Returns +- None + +### C Prototype +`void create_dialog_box_with_response(s16 dialog);` + +[:arrow_up_small:](#) + +
+ +## [create_dialog_box_with_var](#create_dialog_box_with_var) + +### Lua Example +`create_dialog_box_with_var(dialog, dialogVar)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dialog | `integer` | +| dialogVar | `integer` | + +### Returns +- None + +### C Prototype +`void create_dialog_box_with_var(s16 dialog, s32 dialogVar);` + +[:arrow_up_small:](#) + +
+ +## [create_dialog_inverted_box](#create_dialog_inverted_box) + +### Lua Example +`create_dialog_inverted_box(dialog)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dialog | `integer` | + +### Returns +- None + +### C Prototype +`void create_dialog_inverted_box(s16 dialog);` + +[:arrow_up_small:](#) + +
+ ## [reset_dialog_override_color](#reset_dialog_override_color) ### Lua Example @@ -3384,6 +3465,24 @@
+## [reset_dialog_render_state](#reset_dialog_render_state) + +### Lua Example +`reset_dialog_render_state()` + +### Parameters +- None + +### Returns +- None + +### C Prototype +`void reset_dialog_render_state(void);` + +[:arrow_up_small:](#) + +
+ ## [set_dialog_override_color](#set_dialog_override_color) ### Lua Example @@ -3432,6 +3531,26 @@
+## [set_menu_mode](#set_menu_mode) + +### Lua Example +`set_menu_mode(mode)` + +### Parameters +| Field | Type | +| ----- | ---- | +| mode | `integer` | + +### Returns +- None + +### C Prototype +`void set_menu_mode(s16 mode);` + +[:arrow_up_small:](#) + +
+ ## [set_min_dialog_width](#set_min_dialog_width) ### Lua Example diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md index aac96b87..8957c6e6 100644 --- a/docs/lua/functions-5.md +++ b/docs/lua/functions-5.md @@ -1340,6 +1340,24 @@
+## [get_dialog_response](#get_dialog_response) + +### Lua Example +`local integerValue = get_dialog_response()` + +### Parameters +- None + +### Returns +- `integer` + +### C Prototype +`s32 get_dialog_response();` + +[:arrow_up_small:](#) + +
+ ## [get_envfx](#get_envfx) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 69ef7e93..231ed2a0 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -808,10 +808,16 @@
- ingame_menu.h + - [create_dialog_box](functions-3.md#create_dialog_box) + - [create_dialog_box_with_response](functions-3.md#create_dialog_box_with_response) + - [create_dialog_box_with_var](functions-3.md#create_dialog_box_with_var) + - [create_dialog_inverted_box](functions-3.md#create_dialog_inverted_box) - [reset_dialog_override_color](functions-3.md#reset_dialog_override_color) - [reset_dialog_override_pos](functions-3.md#reset_dialog_override_pos) + - [reset_dialog_render_state](functions-3.md#reset_dialog_render_state) - [set_dialog_override_color](functions-3.md#set_dialog_override_color) - [set_dialog_override_pos](functions-3.md#set_dialog_override_pos) + - [set_menu_mode](functions-3.md#set_menu_mode) - [set_min_dialog_width](functions-3.md#set_min_dialog_width)
@@ -1661,6 +1667,7 @@ - [get_date_and_time](functions-5.md#get_date_and_time) - [get_dialog_box_state](functions-5.md#get_dialog_box_state) - [get_dialog_id](functions-5.md#get_dialog_id) + - [get_dialog_response](functions-5.md#get_dialog_response) - [get_envfx](functions-5.md#get_envfx) - [get_environment_region](functions-5.md#get_environment_region) - [get_fog_color](functions-5.md#get_fog_color) diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md index 112d1fc6..486eece3 100644 --- a/docs/lua/guides/hooks.md +++ b/docs/lua/guides/hooks.md @@ -121,7 +121,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh | HOOK_BEFORE_SET_MARIO_ACTION | Called before Mario's action changes Return an action to change the incoming action or `1` to cancel the action change | [MarioState](../structs.md#MarioState) mario, `integer` incomingAction | | HOOK_JOINED_GAME | Called when the local player finishes the join process (if the player isn't the host) | None | | HOOK_ON_OBJECT_ANIM_UPDATE | Called when an object's animation is updated | [Object](../structs.md#Object) objNode | -| HOOK_ON_DIALOG | Called when a dialog appears. Return `false` to prevent it from appearing | `integer` dialogId | +| HOOK_ON_DIALOG | Called when a dialog appears. Return `false` to prevent it from appearing. Return a second parameter as any string to override the text in the textbox | `integer` dialogId | | HOOK_ON_EXIT | Called before the game shuts down | None | | HOOK_DIALOG_SOUND | Called when a dialog box sound is going to play, return a `DS_*` constant to override the sound | `integer` dialogSound | | HOOK_ON_COLLIDE_LEVEL_BOUNDS | Called when a mario collides with the level boundaries | [MarioState](../structs.md#MarioState) mario | diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 12de05f5..1d9ec5b1 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -1156,9 +1156,14 @@ void handle_special_dialog_text(s16 dialogID) { // dialog ID tables, in order } } +static u8 sHookString[255]; +static bool sOverrideDialogString = false; +void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu); void handle_dialog_hook(s16 dialogId) { bool open = false; - smlua_call_event_hooks_int_params_ret_bool(HOOK_ON_DIALOG, dialogId, &open); + const char *str = smlua_call_event_hooks_int_ret_bool_and_string(HOOK_ON_DIALOG, dialogId, &open); + sOverrideDialogString = str != NULL; + if (sOverrideDialogString) { convert_string_ascii_to_sm64(sHookString, str, false); } if (!open) { gDialogLineNum = 1; gDialogBoxState = DIALOG_STATE_CLOSING; @@ -1521,7 +1526,7 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l u8 strChar; - u8 *str = segmented_to_virtual(dialog->str); + u8 *str = sOverrideDialogString ? sHookString : segmented_to_virtual(dialog->str); s8 lineNum = 1; s8 totalLines; @@ -2297,7 +2302,7 @@ void print_peach_letter_message(void) { #endif dialog = segmented_to_virtual(dialogTable[gDialogID]); - str = segmented_to_virtual(dialog->str); + str = sOverrideDialogString ? sHookString : segmented_to_virtual(dialog->str); create_dl_translation_matrix(MENU_MTX_PUSH, 97.0f, 118.0f, 0); @@ -3581,3 +3586,8 @@ void set_dialog_override_color(u8 bgR, u8 bgG, u8 bgB, u8 bgA, u8 textR, u8 text void reset_dialog_override_color(void) { gOverrideDialogColor = 0; } + +void close_dialog_box(u8 state) { + if (state > DIALOG_STATE_CLOSING) { return; } + gDialogBoxState = state; +} diff --git a/src/game/level_info.c b/src/game/level_info.c index 8c9be8f3..6f4e2115 100644 --- a/src/game/level_info.c +++ b/src/game/level_info.c @@ -102,7 +102,7 @@ static char *sm64_to_ascii_char(char *strAscii, const u8 *str64) { return strAscii + 1; } -static void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu) { +void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu) { for (; *strAscii != 0; str64++) { strAscii = ascii_to_sm64_char(str64, strAscii, menu); } diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index ea27d4cb..b11ebba6 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -13252,6 +13252,76 @@ int smlua_func_set_first_person_enabled(lua_State* L) { // ingame_menu.h // /////////////////// +int smlua_func_create_dialog_box(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", "create_dialog_box", 1, top); + return 0; + } + + s16 dialog = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box"); return 0; } + + create_dialog_box(dialog); + + return 1; +} + +int smlua_func_create_dialog_box_with_response(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", "create_dialog_box_with_response", 1, top); + return 0; + } + + s16 dialog = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box_with_response"); return 0; } + + create_dialog_box_with_response(dialog); + + return 1; +} + +int smlua_func_create_dialog_box_with_var(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "create_dialog_box_with_var", 2, top); + return 0; + } + + s16 dialog = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_box_with_var"); return 0; } + s32 dialogVar = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "create_dialog_box_with_var"); return 0; } + + create_dialog_box_with_var(dialog, dialogVar); + + return 1; +} + +int smlua_func_create_dialog_inverted_box(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", "create_dialog_inverted_box", 1, top); + return 0; + } + + s16 dialog = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "create_dialog_inverted_box"); return 0; } + + create_dialog_inverted_box(dialog); + + return 1; +} + int smlua_func_reset_dialog_override_color(UNUSED lua_State* L) { if (L == NULL) { return 0; } @@ -13282,6 +13352,21 @@ int smlua_func_reset_dialog_override_pos(UNUSED lua_State* L) { return 1; } +int smlua_func_reset_dialog_render_state(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "reset_dialog_render_state", 0, top); + return 0; + } + + + reset_dialog_render_state(); + + return 1; +} + int smlua_func_set_dialog_override_color(lua_State* L) { if (L == NULL) { return 0; } @@ -13332,6 +13417,23 @@ int smlua_func_set_dialog_override_pos(lua_State* L) { return 1; } +int smlua_func_set_menu_mode(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", "set_menu_mode", 1, top); + return 0; + } + + s16 mode = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "set_menu_mode"); return 0; } + + set_menu_mode(mode); + + return 1; +} + int smlua_func_set_min_dialog_width(lua_State* L) { if (L == NULL) { return 0; } @@ -29402,6 +29504,21 @@ int smlua_func_get_dialog_id(UNUSED lua_State* L) { return 1; } +int smlua_func_get_dialog_response(UNUSED lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_dialog_response", 0, top); + return 0; + } + + + lua_pushinteger(L, get_dialog_response()); + + return 1; +} + int smlua_func_get_envfx(UNUSED lua_State* L) { if (L == NULL) { return 0; } @@ -32781,10 +32898,16 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "set_first_person_enabled", smlua_func_set_first_person_enabled); // ingame_menu.h + smlua_bind_function(L, "create_dialog_box", smlua_func_create_dialog_box); + smlua_bind_function(L, "create_dialog_box_with_response", smlua_func_create_dialog_box_with_response); + smlua_bind_function(L, "create_dialog_box_with_var", smlua_func_create_dialog_box_with_var); + smlua_bind_function(L, "create_dialog_inverted_box", smlua_func_create_dialog_inverted_box); smlua_bind_function(L, "reset_dialog_override_color", smlua_func_reset_dialog_override_color); smlua_bind_function(L, "reset_dialog_override_pos", smlua_func_reset_dialog_override_pos); + smlua_bind_function(L, "reset_dialog_render_state", smlua_func_reset_dialog_render_state); smlua_bind_function(L, "set_dialog_override_color", smlua_func_set_dialog_override_color); smlua_bind_function(L, "set_dialog_override_pos", smlua_func_set_dialog_override_pos); + smlua_bind_function(L, "set_menu_mode", smlua_func_set_menu_mode); smlua_bind_function(L, "set_min_dialog_width", smlua_func_set_min_dialog_width); // interaction.h @@ -33589,6 +33712,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "get_date_and_time", smlua_func_get_date_and_time); smlua_bind_function(L, "get_dialog_box_state", smlua_func_get_dialog_box_state); smlua_bind_function(L, "get_dialog_id", smlua_func_get_dialog_id); + smlua_bind_function(L, "get_dialog_response", smlua_func_get_dialog_response); smlua_bind_function(L, "get_envfx", smlua_func_get_envfx); smlua_bind_function(L, "get_environment_region", smlua_func_get_environment_region); smlua_bind_function(L, "get_fog_color", smlua_func_get_fog_color); diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index 574c18e6..da7338ad 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -1052,6 +1052,42 @@ void smlua_call_event_hooks_graph_node_object_and_int_param(enum LuaHookedEventT } } +const char *smlua_call_event_hooks_int_ret_bool_and_string(enum LuaHookedEventType hookType, s32 param, bool* returnValue) { + lua_State* L = gLuaState; + if (L == NULL) { return NULL; } + *returnValue = true; + const char *retString = NULL; + + 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 param + lua_pushinteger(L, param); + + // call the callback + if (0 != smlua_call_hook(L, 1, 2, 0, hook->mod[i])) { + LOG_LUA("Failed to call the callback: %u", hookType); + continue; + } + + // output the return values + if (lua_type(L, -2) == LUA_TBOOLEAN) { + *returnValue = smlua_to_boolean(L, -2); + } + if (lua_type(L, -1) == LUA_TSTRING) { + retString = smlua_to_string(L, -1); + lua_settop(L, prevTop); + return retString; + } + lua_settop(L, prevTop); + } + return NULL; +} + //////////////////// // hooked actions // //////////////////// diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 56b5479b..47e6ac96 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -150,6 +150,7 @@ bool smlua_call_event_hooks_mario_param_ret_float(enum LuaHookedEventType hookTy bool smlua_call_event_hooks_mario_param_and_int_and_int_ret_int(enum LuaHookedEventType hookType, struct MarioState* m, s32 param, u32 args, s32* returnValue); void smlua_call_event_hooks_graph_node_object_and_int_param(enum LuaHookedEventType hookType, struct GraphNodeObject* node, s32 param); void smlua_call_event_hooks_on_seq_load(enum LuaHookedEventType hookType, u32 player, u32 seqId, s32 loadAsync, u8* returnValue); +const char *smlua_call_event_hooks_int_ret_bool_and_string(enum LuaHookedEventType hookType, s32 param, bool* returnValue); enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior); const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior); diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c index db4bd4d9..3de3aae3 100644 --- a/src/pc/lua/utils/smlua_misc_utils.c +++ b/src/pc/lua/utils/smlua_misc_utils.c @@ -654,3 +654,9 @@ const char* get_os_name(void) { return "Unknown"; #endif } + +/// + +s32 get_dialog_response() { + return gDialogResponse; +} diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h index 2e343651..72f41cb0 100644 --- a/src/pc/lua/utils/smlua_misc_utils.h +++ b/src/pc/lua/utils/smlua_misc_utils.h @@ -163,4 +163,6 @@ void reset_window_title(void); const char* get_os_name(void); +s32 get_dialog_response(); + #endif