diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 5a708ed9..701ff3dc 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -4404,7 +4404,7 @@ PLAYER_INTERACTIONS_SOLID = 1 PLAYER_INTERACTIONS_PVP = 2 --- @type integer -MAX_RX_SEQ_IDS = 16 +MAX_RX_SEQ_IDS = 64 --- @type integer NETWORK_PLAYER_TIMEOUT = 10 @@ -7849,7 +7849,10 @@ HOOK_ON_SET_CAMERA_MODE = 18 HOOK_ON_OBJECT_RENDER = 19 --- @type LuaHookedEventType -HOOK_MAX = 20 +HOOK_ON_DEATH = 20 + +--- @type LuaHookedEventType +HOOK_MAX = 21 --- @class ModelExtendedId diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 277ab463..73bbd5f7 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -3930,6 +3930,12 @@ function hurt_and_set_mario_action(m, action, actionArg, hurtCounter) -- ... end +--- @param m MarioState +--- @return nil +function init_single_mario(m) + -- ... +end + --- @param m MarioState --- @return integer function is_anim_at_end(m) diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 816ee8a2..0532526c 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -2754,7 +2754,8 @@ | HOOK_GET_STAR_COLLECTION_DIALOG | 17 | | HOOK_ON_SET_CAMERA_MODE | 18 | | HOOK_ON_OBJECT_RENDER | 19 | -| HOOK_MAX | 20 | +| HOOK_ON_DEATH | 20 | +| HOOK_MAX | 21 | [:arrow_up_small:](#) diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 3794259e..584fede3 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -765,6 +765,7 @@ - [find_mario_anim_flags_and_translation](#find_mario_anim_flags_and_translation) - [force_idle_state](#force_idle_state) - [hurt_and_set_mario_action](#hurt_and_set_mario_action) + - [init_single_mario](#init_single_mario) - [is_anim_at_end](#is_anim_at_end) - [is_anim_past_end](#is_anim_past_end) - [is_anim_past_frame](#is_anim_past_frame) @@ -14941,6 +14942,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [init_single_mario](#init_single_mario) + +### Lua Example +`init_single_mario(m)` + +### Parameters +| Field | Type | +| ----- | ---- | +| m | [MarioState](structs.md#MarioState) | + +### Returns +- None + +### C Prototype +`void init_single_mario(struct MarioState* m);` + +[:arrow_up_small:](#) + +
+ ## [is_anim_at_end](#is_anim_at_end) ### Lua Example diff --git a/docs/lua/hooks.md b/docs/lua/hooks.md index 6b8dd65d..07021327 100644 --- a/docs/lua/hooks.md +++ b/docs/lua/hooks.md @@ -106,6 +106,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh | HOOK_GET_STAR_COLLECTION_DIALOG | Called when the local player collects a star, return a [DialogId](constants.md#enum-DialogId) to show a message | None | | HOOK_ON_SET_CAMERA_MODE | Called when the camera mode gets set, return `false` to prevent the camera mode from being set | [Camera](structs.md#Camera), `integer` mode, `integer` frames | | HOOK_ON_OBJECT_RENDER | Called right before an object is rendered. **Note:** You must set the `hookRender` field of the object to a non-zero value | [Object](structs.md#Object) | +| HOOK_ON_DEATH | Called when the local player dies, return `false` to prevent normal death sequence | [MarioState](structs.md#MarioState) | ### Parameters diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 45412c8f..57f5788c 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -858,16 +858,24 @@ static void level_cmd_place_object_ext(void) { u16 modIndex = gLevelScriptModIndex; const char* behStr = dynos_level_get_token(CMD_GET(u32, 20)); + if (gLevelScriptModIndex == -1) { + LOG_ERROR("Could not find level script mod index"); + sCurrentCmd = CMD_NEXT; + return; + } + gSmLuaConvertSuccess = true; + gSmLuaSuppressErrors = true; enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr); + gSmLuaSuppressErrors = false; if (!gSmLuaConvertSuccess) { gSmLuaConvertSuccess = true; behId = smlua_get_any_mod_variable(behStr); } - if ((gLevelScriptModIndex == -1) || !gSmLuaConvertSuccess) { - LOG_ERROR("Failed to place custom object: %u :: %s", behId, behStr); + if (!gSmLuaConvertSuccess) { + LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr); sCurrentCmd = CMD_NEXT; return; } @@ -907,22 +915,37 @@ static void level_cmd_place_object_ext2(void) { const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20)); const char* behStr = dynos_level_get_token(CMD_GET(u32, 24)); + if (gLevelScriptModIndex == -1) { + LOG_ERROR("Could not find level script mod index"); + sCurrentCmd = CMD_NEXT; + return; + } + gSmLuaConvertSuccess = true; + gSmLuaSuppressErrors = true; enum ModelExtendedId modelId = smlua_get_mod_variable(modIndex, modelStr); + gSmLuaSuppressErrors = false; if (!gSmLuaConvertSuccess) { gSmLuaConvertSuccess = true; modelId = smlua_get_any_mod_variable(modelStr); } + if (!gSmLuaConvertSuccess) { + LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr); + sCurrentCmd = CMD_NEXT; + return; + } gSmLuaConvertSuccess = true; + gSmLuaSuppressErrors = true; enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr); + gSmLuaSuppressErrors = false; if (!gSmLuaConvertSuccess) { gSmLuaConvertSuccess = true; behId = smlua_get_any_mod_variable(behStr); } - if ((gLevelScriptModIndex == -1) || !gSmLuaConvertSuccess) { - LOG_ERROR("Failed to place custom object: %u, %u", modelId, behId); + if (!gSmLuaConvertSuccess) { + LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr); sCurrentCmd = CMD_NEXT; return; } diff --git a/src/game/interaction.c b/src/game/interaction.c index c02ad828..3f842227 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -2209,6 +2209,10 @@ void check_death_barrier(struct MarioState *m) { if (m->playerIndex != 0) { return; } if (m->pos[1] < m->floorHeight + 2048.0f) { + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return; } + if (mario_can_bubble(m)) { switch (gCurrCourseNum) { case COURSE_COTMC: // (20) Cavern of the Metal Cap diff --git a/src/game/mario.c b/src/game/mario.c index 2b6f8848..376017c0 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2107,7 +2107,7 @@ s32 force_idle_state(struct MarioState* m) { * INITIALIZATION * **************************************************/ -static void init_single_mario(struct MarioState* m) { +void init_single_mario(struct MarioState* m) { u16 playerIndex = m->playerIndex; struct SpawnInfo* spawnInfo = &gPlayerSpawnInfos[playerIndex]; diff --git a/src/game/mario.h b/src/game/mario.h index 0407d291..67aa916a 100644 --- a/src/game/mario.h +++ b/src/game/mario.h @@ -54,6 +54,7 @@ s32 transition_submerged_to_walking(struct MarioState *m); s32 set_water_plunge_action(struct MarioState *m); s32 execute_mario_action(UNUSED struct Object *o); s32 force_idle_state(struct MarioState* m); +void init_single_mario(struct MarioState* m); void init_mario(void); void init_mario_from_save_file(void); diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 2281d91b..3c64c3ed 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -1576,11 +1576,20 @@ s32 act_lava_boost(struct MarioState *m) { if (m != &gMarioStates[0]) { // never kill remote marios m->health = 0x100; - } else if (mario_can_bubble(m)) { - m->health = 0xFF; - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { + reset_rumble_timers(m); + return FALSE; + } + + if (mario_can_bubble(m)) { + m->health = 0xFF; + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index eafe1ddc..bed82c7a 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -35,6 +35,7 @@ #include "pc/configfile.h" #include "pc/network/network.h" #include "pc/lua/smlua.h" +#include "pc/lua/smlua_hooks.h" // TODO: put this elsewhere enum SaveOption { SAVE_OPT_SAVE_AND_CONTINUE = 1, /*SAVE_OPT_SAVE_AND_QUIT, SAVE_OPT_SAVE_EXIT_GAME,*/ SAVE_OPT_CONTINUE_DONT_SAVE }; @@ -777,10 +778,16 @@ s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWa if (animFrame == frameToDeathWarp) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return animFrame; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } m->marioBodyState->eyeState = MARIO_EYES_DEAD; @@ -842,12 +849,18 @@ s32 act_quicksand_death(struct MarioState *m) { if ((m->quicksandDepth += 5.0f) >= 180.0f) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + m->actionState = 2; + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return FALSE; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } - m->actionState = 2; } } stationary_ground_step(m); @@ -862,11 +875,17 @@ s32 act_eaten_by_bubba(struct MarioState *m) { if (m->actionTimer++ == 60) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - m->health = 0xFF; - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return FALSE; } + + if (mario_can_bubble(m)) { + m->health = 0xFF; + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } @@ -1743,15 +1762,21 @@ s32 act_squished(struct MarioState *m) { if (m->playerIndex != 0) { // never kill remote marios m->health = 0x100; - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - // 0 units of health - m->health = 0x00FF; - m->hurtCounter = 0; - level_trigger_warp(m, WARP_OP_DEATH); - // woosh, he's gone! - set_mario_action(m, ACT_DISAPPEARED, 0); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return FALSE; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + // 0 units of health + m->health = 0x00FF; + m->hurtCounter = 0; + level_trigger_warp(m, WARP_OP_DEATH); + // woosh, he's gone! + set_mario_action(m, ACT_DISAPPEARED, 0); + } } } stop_and_set_height_to_floor(m); diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index 1a007997..9e48096c 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -20,6 +20,7 @@ #include "pc/configfile.h" #include "pc/network/network.h" #include "pc/lua/smlua.h" +#include "pc/lua/smlua_hooks.h" #define MIN_SWIM_STRENGTH 160 #define MIN_SWIM_SPEED 16.0f @@ -944,10 +945,16 @@ static s32 act_drowning(struct MarioState *m) { if (m->marioObj->header.gfx.animInfo.animFrame == 30) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return FALSE; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } break; @@ -972,10 +979,16 @@ static s32 act_water_death(struct MarioState *m) { if (set_mario_animation(m, MARIO_ANIM_WATER_DYING) == 35) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { return FALSE; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } @@ -1090,10 +1103,16 @@ static s32 act_caught_in_whirlpool(struct MarioState *m) { if (distance < 16.1f && m->actionTimer++ == 16) { if (m->playerIndex != 0) { // do nothing - } else if (mario_can_bubble(m)) { - mario_set_bubbled(m); } else { - level_trigger_warp(m, WARP_OP_DEATH); + bool allowDeath = true; + smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath); + if (!allowDeath) { reset_rumble_timers(m); return FALSE; } + + if (mario_can_bubble(m)) { + mario_set_bubbled(m); + } else { + level_trigger_warp(m, WARP_OP_DEATH); + } } } } diff --git a/src/pc/lua/smlua.c b/src/pc/lua/smlua.c index 47049385..a7b9342c 100644 --- a/src/pc/lua/smlua.c +++ b/src/pc/lua/smlua.c @@ -8,6 +8,7 @@ lua_State* gLuaState = NULL; u8 gLuaInitializingScript = 0; +u8 gSmLuaSuppressErrors = 0; struct Mod* gLuaLoadingMod = NULL; struct Mod* gLuaActiveMod = NULL; struct Mod* gLuaLastHookMod = NULL; diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index 26a6d4db..92de306f 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -19,7 +19,7 @@ #include "pc/debuglog.h" -#define LOG_LUA(...) ( _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error() ) +#define LOG_LUA(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(); } } #ifdef DEVELOPMENT #define LUA_STACK_CHECK_BEGIN() int __LUA_STACK_TOP = lua_gettop(gLuaState) @@ -31,6 +31,7 @@ extern lua_State* gLuaState; extern u8 gLuaInitializingScript; +extern u8 gSmLuaSuppressErrors; extern struct Mod* gLuaLoadingMod; extern struct Mod* gLuaActiveMod; extern struct Mod* gLuaLastHookMod; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 93407df0..330865de 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1656,7 +1656,7 @@ char gSmluaConstants[] = "" "UNKNOWN_GLOBAL_INDEX = (-1)\n" "UNKNOWN_NETWORK_INDEX = (-1)\n" "NETWORK_PLAYER_TIMEOUT = 10\n" -"MAX_RX_SEQ_IDS = 16\n" +"MAX_RX_SEQ_IDS = 64\n" "NPT_UNKNOWN = 0\n" "NPT_LOCAL = 1\n" "NPT_SERVER = 2\n" @@ -2797,7 +2797,8 @@ char gSmluaConstants[] = "" "HOOK_GET_STAR_COLLECTION_DIALOG = 17\n" "HOOK_ON_SET_CAMERA_MODE = 18\n" "HOOK_ON_OBJECT_RENDER = 19\n" -"HOOK_MAX = 20\n" +"HOOK_ON_DEATH = 20\n" +"HOOK_MAX = 21\n" "E_MODEL_NONE = 0\n" "E_MODEL_MARIO = 1\n" "E_MODEL_SMOKE = 2\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index a4d246d9..e633dbf8 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -8026,6 +8026,17 @@ int smlua_func_hurt_and_set_mario_action(lua_State* L) { return 1; } +int smlua_func_init_single_mario(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 1)) { return 0; } + + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE); + if (!gSmLuaConvertSuccess) { return 0; } + + init_single_mario(m); + + return 1; +} + int smlua_func_is_anim_at_end(lua_State* L) { if(!smlua_functions_valid_param_count(L, 1)) { return 0; } @@ -16549,6 +16560,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "find_mario_anim_flags_and_translation", smlua_func_find_mario_anim_flags_and_translation); smlua_bind_function(L, "force_idle_state", smlua_func_force_idle_state); smlua_bind_function(L, "hurt_and_set_mario_action", smlua_func_hurt_and_set_mario_action); + smlua_bind_function(L, "init_single_mario", smlua_func_init_single_mario); smlua_bind_function(L, "is_anim_at_end", smlua_func_is_anim_at_end); smlua_bind_function(L, "is_anim_past_end", smlua_func_is_anim_past_end); smlua_bind_function(L, "is_anim_past_frame", smlua_func_is_anim_past_frame); diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index bea50c2b..6d06ea0d 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -223,6 +223,37 @@ void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct } } +void smlua_call_event_hooks_mario_param_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m, bool* returnValue) { + 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); + + // call the callback + if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i])) { + LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1)); + smlua_logline(); + continue; + } + + // output the return value + if (lua_type(L, -1) == LUA_TBOOLEAN) { + *returnValue = smlua_to_boolean(L, -1); + } + lua_settop(L, prevTop); + } +} + void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2) { lua_State* L = gLuaState; if (L == NULL) { return; } diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index e6e8d3c7..b0804df8 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -28,6 +28,7 @@ enum LuaHookedEventType { HOOK_GET_STAR_COLLECTION_DIALOG, HOOK_ON_SET_CAMERA_MODE, HOOK_ON_OBJECT_RENDER, + HOOK_ON_DEATH, HOOK_MAX, }; @@ -52,6 +53,7 @@ static char* LuaHookedEventTypeName[] = { "HOOK_GET_STAR_COLLECTION_DIALOG", "HOOK_ON_SET_CAMERA_MODE", "HOOK_ON_OBJECT_RENDER", + "HOOK_ON_DEATH", "HOOK_MAX" }; @@ -61,6 +63,7 @@ void smlua_call_event_hooks(enum LuaHookedEventType hookType); void smlua_call_event_hooks_bool_param(enum LuaHookedEventType hookType, bool value); void smlua_call_event_hooks_bool_param_ret_bool(enum LuaHookedEventType hookType, bool value, bool* returnValue); void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m); +void smlua_call_event_hooks_mario_param_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m, bool* returnValue); void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2); void smlua_call_event_hooks_mario_params_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2, bool* returnValue); void smlua_call_event_hooks_interact_params(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType, bool interactValue); diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index 97cd4ef1..8db9df13 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -397,6 +397,7 @@ s64 smlua_get_mod_variable(u16 modIndex, const char* variable) { s64 smlua_get_any_mod_variable(const char* variable) { lua_State* L = gLuaState; + u8 prevSuppress = gSmLuaSuppressErrors; s64 value = 0; for (s32 i = 0; i < gActiveMods.entryCount; i++) { @@ -406,15 +407,18 @@ s64 smlua_get_any_mod_variable(const char* variable) { int prevTop = lua_gettop(L); lua_getglobal(L, "_G"); // get global table lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table + gSmLuaSuppressErrors = true; value = smlua_get_integer_field(-1, (char*)variable); lua_settop(L, prevTop); if (gSmLuaConvertSuccess) { + gSmLuaSuppressErrors = prevSuppress; return value; } } // return variable + gSmLuaSuppressErrors = prevSuppress; return value; }