diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index e7a840861..ca61340b4 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -10364,19 +10364,22 @@ HOOK_MAX = 53 --- @class LuaModMenuElementType --- @type LuaModMenuElementType -MOD_MENU_ELEMENT_BUTTON = 0 +MOD_MENU_ELEMENT_TEXT = 0 --- @type LuaModMenuElementType -MOD_MENU_ELEMENT_CHECKBOX = 1 +MOD_MENU_ELEMENT_BUTTON = 1 --- @type LuaModMenuElementType -MOD_MENU_ELEMENT_SLIDER = 2 +MOD_MENU_ELEMENT_CHECKBOX = 2 --- @type LuaModMenuElementType -MOD_MENU_ELEMENT_INPUTBOX = 3 +MOD_MENU_ELEMENT_SLIDER = 3 --- @type LuaModMenuElementType -MOD_MENU_ELEMENT_MAX = 4 +MOD_MENU_ELEMENT_INPUTBOX = 4 + +--- @type LuaModMenuElementType +MOD_MENU_ELEMENT_MAX = 5 --- @class HudDisplayFlags diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua index 2f1b0bd85..452789335 100644 --- a/autogen/lua_definitions/manual.lua +++ b/autogen/lua_definitions/manual.lua @@ -160,8 +160,16 @@ function hook_on_sync_table_change(syncTable, field, tag, func) -- ... end +--- @param message string The message for the text to show +--- @return integer +--- Hooks DJUI text into the mod menu +function hook_mod_menu_text(message) + -- ... +end + --- @param name string The text to show on the button --- @param func fun(index:integer) The function that is called when the button is pressed +--- @return integer --- Hooks a DJUI button into the mod menu function hook_mod_menu_button(name, func) -- ... @@ -170,6 +178,7 @@ end --- @param name string The text to show on the left --- @param defaultValue boolean The default state of the checkbox --- @param func fun(index:integer, value:boolean) The function that is called when the checkbox is changed +--- @return integer --- Hooks a DJUI checkbox into the mod menu function hook_mod_menu_checkbox(name, defaultValue, func) -- ... @@ -180,6 +189,7 @@ end --- @param min integer The lowest the slider can go --- @param max integer The highest the slider can go --- @param func fun(index:integer, value:integer) The function that is called when the value of the slider changes +--- @return integer --- Hooks a DJUI slider into the mod menu function hook_mod_menu_slider(name, defaultValue, min, max, func) -- ... @@ -189,6 +199,7 @@ end --- @param defaultValue string The default text in the inputbox --- @param stringLength integer The max length of the inputbox --- @param func fun(index:integer, value:string) The function that is called when the value of the inputbox changes +--- @return integer --- Hooks a DJUI inputbox into the mod menu function hook_mod_menu_inputbox(name, defaultValue, stringLength, func) -- ... diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 91480a8a1..de77b2f1a 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -3756,11 +3756,12 @@ ### [enum LuaModMenuElementType](#LuaModMenuElementType) | Identifier | Value | | :--------- | :---- | -| MOD_MENU_ELEMENT_BUTTON | 0 | -| MOD_MENU_ELEMENT_CHECKBOX | 1 | -| MOD_MENU_ELEMENT_SLIDER | 2 | -| MOD_MENU_ELEMENT_INPUTBOX | 3 | -| MOD_MENU_ELEMENT_MAX | 4 | +| MOD_MENU_ELEMENT_TEXT | 0 | +| MOD_MENU_ELEMENT_BUTTON | 1 | +| MOD_MENU_ELEMENT_CHECKBOX | 2 | +| MOD_MENU_ELEMENT_SLIDER | 3 | +| MOD_MENU_ELEMENT_INPUTBOX | 4 | +| MOD_MENU_ELEMENT_MAX | 5 | [:arrow_up_small:](#) diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md index 6033e553a..020a86c59 100644 --- a/docs/lua/guides/hooks.md +++ b/docs/lua/guides/hooks.md @@ -9,6 +9,7 @@ Hooks are a way for SM64 to trigger Lua code, whereas the functions listed in [f - [hook_event](#hook_event) - [hook_mario_action](#hook_mario_action) - [hook_on_sync_table_change](#hook_on_sync_table_change) +- [hook_mod_menu_text](#hook_mod_menu_text) - [hook_mod_menu_button](#hook_mod_menu_button) - [hook_mod_menu_checkbox](#hook_mod_menu_checkbox) - [hook_mod_menu_slider](#hook_mod_menu_slider) @@ -286,6 +287,25 @@ gGlobalSyncTable.testingField = "hello"
+## [hook_mod_menu_text](#hook_mod_menu_text) +`hook_mod_menu_text()` allows Lua to add text labels to their designated mod menu submenu. + +### Parameters + +| Field | Type | +| ----- | ---- | +| message | `string` | + +### Lua Example + +```lua +hook_mod_menu_text("Rise and shine, Mr. Freeman.") +``` + +[:arrow_up_small:](#) + +
+ ## [hook_mod_menu_button](#hook_mod_menu_button) `hook_mod_menu_button()` allows Lua to add buttons to their designated mod menu submenu. @@ -293,7 +313,7 @@ gGlobalSyncTable.testingField = "hello" | Field | Type | | ----- | ---- | -| message | `string` | +| name | `string` | | func | `Lua Function` (`integer` index) | ### Lua Example @@ -329,7 +349,7 @@ hook_mod_menu_button("Open Menu 2", on_open_menu) | Field | Type | | ----- | ---- | -| message | `string` | +| name | `string` | | defaultValue | `boolean` | | func | `Lua Function` (`integer` index, `boolean` value) | @@ -365,7 +385,7 @@ hook_mod_menu_checkbox("Noclip Mode", false, on_set_player_mode) | Field | Type | | ----- | ---- | -| message | `string` | +| name | `string` | | defaultValue | `integer` | | min | `integer` | | max | `integer` | @@ -394,7 +414,7 @@ hook_mod_menu_slider("Time Scale", 1, 0, 10, on_set_time_scale) | Field | Type | | ----- | ---- | -| message | `string` | +| name | `string` | | defaultValue | `string` | | stringLength | `integer` | | func | `Lua Function` (`integer` index, `string` value) | diff --git a/src/pc/djui/djui_panel_mod_menu.c b/src/pc/djui/djui_panel_mod_menu.c index a2ff23fd8..9ee16acb3 100644 --- a/src/pc/djui/djui_panel_mod_menu.c +++ b/src/pc/djui/djui_panel_mod_menu.c @@ -28,14 +28,14 @@ void djui_panel_mod_menu_mod_button(struct DjuiBase* caller) { } } -void djui_panel_mod_menu_mod_checkbox(struct DjuiBase* caller) { +static void djui_panel_mod_menu_mod_checkbox(struct DjuiBase* caller) { struct LuaHookedModMenuElement* hooked = &gHookedModMenuElements[caller->tag]; smlua_call_mod_menu_element_hook(hooked, caller->tag); struct DjuiCheckbox* checkbox = (struct DjuiCheckbox*)caller; djui_text_set_text(checkbox->text, hooked->name); } -void djui_panel_mod_menu_mod_slider(struct DjuiBase* caller) { +static void djui_panel_mod_menu_mod_slider(struct DjuiBase* caller) { struct LuaHookedModMenuElement* hooked = &gHookedModMenuElements[caller->tag]; smlua_call_mod_menu_element_hook(hooked, caller->tag); struct DjuiSlider* slider = (struct DjuiSlider*)caller; @@ -52,6 +52,17 @@ static void djui_panel_mod_menu_mod_inputbox(struct DjuiBase* caller) { static void djui_panel_mod_menu_mod_create_element(struct DjuiBase* parent, int i) { struct LuaHookedModMenuElement* hooked = &gHookedModMenuElements[i]; switch (hooked->element) { + case MOD_MENU_ELEMENT_TEXT: { + struct DjuiText* text = djui_text_create(parent, hooked->name); + djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_color(&text->base, 220, 220, 220, 255); + djui_base_set_size(&text->base, 1.0f, 64); + djui_base_set_alignment(&text->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP); + djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); + djui_text_set_drop_shadow(text, 64, 64, 64, 100); + text->base.tag = i; + break; + } case MOD_MENU_ELEMENT_BUTTON: { struct DjuiButton* button = djui_button_create(parent, hooked->name, DJUI_BUTTON_STYLE_NORMAL, djui_panel_mod_menu_mod_button); button->base.tag = i; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index ff8753821..5f8aa12d5 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3621,11 +3621,12 @@ char gSmluaConstants[] = "" "ACTION_HOOK_EVERY_FRAME=0\n" "ACTION_HOOK_GRAVITY=1\n" "ACTION_HOOK_MAX=2\n" -"MOD_MENU_ELEMENT_BUTTON=0\n" -"MOD_MENU_ELEMENT_CHECKBOX=1\n" -"MOD_MENU_ELEMENT_SLIDER=2\n" -"MOD_MENU_ELEMENT_INPUTBOX=3\n" -"MOD_MENU_ELEMENT_MAX=4\n" +"MOD_MENU_ELEMENT_TEXT=0\n" +"MOD_MENU_ELEMENT_BUTTON=1\n" +"MOD_MENU_ELEMENT_CHECKBOX=2\n" +"MOD_MENU_ELEMENT_SLIDER=3\n" +"MOD_MENU_ELEMENT_INPUTBOX=4\n" +"MOD_MENU_ELEMENT_MAX=5\n" "HUD_DISPLAY_LIVES=0\n" "HUD_DISPLAY_COINS=1\n" "HUD_DISPLAY_STARS=2\n" diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index 39d68e636..6eee3dbaa 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -1984,6 +1984,38 @@ int smlua_hook_on_sync_table_change(lua_State* L) { struct LuaHookedModMenuElement gHookedModMenuElements[MAX_HOOKED_MOD_MENU_ELEMENTS] = { 0 }; int gHookedModMenuElementsCount = 0; +int smlua_hook_mod_menu_text(lua_State* L) { + if (L == NULL) { return 0; } + if (!smlua_functions_valid_param_count(L, 1)) { return 0; } + + if (gHookedModMenuElementsCount >= MAX_HOOKED_MOD_MENU_ELEMENTS) { + LOG_LUA_LINE("Hooked mod menu element exceeded maximum references!"); + return 0; + } + + const char* name = smlua_to_string(L, 1); + if (name == NULL || strlen(name) == 0 || !gSmLuaConvertSuccess) { + LOG_LUA_LINE("Hook mod menu element: tried to hook invalid element"); + return 0; + } + + struct LuaHookedModMenuElement* hooked = &gHookedModMenuElements[gHookedModMenuElementsCount]; + hooked->element = MOD_MENU_ELEMENT_TEXT; + snprintf(hooked->name, 64, "%s", name); + hooked->boolValue = false; + hooked->uintValue = 0; + hooked->stringValue[0] = '\0'; + hooked->length = 0; + hooked->sliderMin = 0; + hooked->sliderMax = 0; + hooked->reference = 0; + hooked->mod = gLuaActiveMod; + + lua_pushinteger(L, gHookedModMenuElementsCount); + gHookedModMenuElementsCount++; + return 1; +} + int smlua_hook_mod_menu_button(lua_State* L) { if (L == NULL) { return 0; } if (!smlua_functions_valid_param_count(L, 2)) { return 0; } @@ -2017,6 +2049,7 @@ int smlua_hook_mod_menu_button(lua_State* L) { hooked->reference = ref; hooked->mod = gLuaActiveMod; + lua_pushinteger(L, gHookedModMenuElementsCount); gHookedModMenuElementsCount++; return 1; } @@ -2060,6 +2093,7 @@ int smlua_hook_mod_menu_checkbox(lua_State* L) { hooked->reference = ref; hooked->mod = gLuaActiveMod; + lua_pushinteger(L, gHookedModMenuElementsCount); gHookedModMenuElementsCount++; return 1; } @@ -2115,6 +2149,7 @@ int smlua_hook_mod_menu_slider(lua_State* L) { hooked->reference = ref; hooked->mod = gLuaActiveMod; + lua_pushinteger(L, gHookedModMenuElementsCount); gHookedModMenuElementsCount++; return 1; } @@ -2165,6 +2200,7 @@ int smlua_hook_mod_menu_inputbox(lua_State* L) { hooked->reference = ref; hooked->mod = gLuaActiveMod; + lua_pushinteger(L, gHookedModMenuElementsCount); gHookedModMenuElementsCount++; return 1; } @@ -2275,6 +2311,8 @@ void smlua_call_mod_menu_element_hook(struct LuaHookedModMenuElement* hooked, in u8 params = 2; lua_pushinteger(L, index); switch (hooked->element) { + case MOD_MENU_ELEMENT_TEXT: + params = 1; case MOD_MENU_ELEMENT_BUTTON: params = 1; break; @@ -2336,7 +2374,7 @@ void smlua_clear_hooks(void) { for (int i = 0; i < gHookedModMenuElementsCount; i++) { struct LuaHookedModMenuElement* hooked = &gHookedModMenuElements[i]; - hooked->element = MOD_MENU_ELEMENT_BUTTON; + hooked->element = MOD_MENU_ELEMENT_TEXT; hooked->name[0] = '\0'; hooked->boolValue = false; hooked->uintValue = 0; @@ -2388,6 +2426,7 @@ void smlua_bind_hooks(void) { smlua_bind_function(L, "hook_chat_command", smlua_hook_chat_command); smlua_bind_function(L, "hook_on_sync_table_change", smlua_hook_on_sync_table_change); smlua_bind_function(L, "hook_behavior", smlua_hook_behavior); + smlua_bind_function(L, "hook_mod_menu_text", smlua_hook_mod_menu_text); smlua_bind_function(L, "hook_mod_menu_button", smlua_hook_mod_menu_button); smlua_bind_function(L, "hook_mod_menu_checkbox", smlua_hook_mod_menu_checkbox); smlua_bind_function(L, "hook_mod_menu_slider", smlua_hook_mod_menu_slider); diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index f55ad4981..eb7119fac 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -140,6 +140,7 @@ static const char* LuaActionHookTypeArgName[] = { #define MAX_HOOKED_MOD_MENU_ELEMENTS 256 enum LuaModMenuElementType { + MOD_MENU_ELEMENT_TEXT, MOD_MENU_ELEMENT_BUTTON, MOD_MENU_ELEMENT_CHECKBOX, MOD_MENU_ELEMENT_SLIDER,