From 96932f5bf17cf5b555534880f3e0bbc2bf5494de Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Tue, 31 Dec 2024 01:23:13 +0100 Subject: [PATCH] Custom geo function and switch nodes with Lua callback (#593) --- autogen/convert_functions.py | 2 +- autogen/convert_structs.py | 1 + autogen/lua_definitions/functions.lua | 12 +++++ data/dynos.c.h | 3 +- data/dynos.cpp.h | 5 ++- data/dynos_bin_geo.cpp | 42 ++++++++++++++--- data/dynos_bin_utils.cpp | 2 +- data/dynos_c.cpp | 8 +++- data/dynos_mgr_actor.cpp | 23 +++++++++- docs/lua/functions-4.md | 42 +++++++++++++++++ docs/lua/functions.md | 2 + include/geo_commands.h | 17 +++++++ src/engine/geo_layout.c | 40 +++++++++++++++++ src/engine/geo_layout.h | 2 + src/engine/graph_node.c | 10 +++++ src/engine/graph_node.h | 2 + src/game/mario_misc.c | 65 ++++++++++++++++++++++++++- src/game/mario_misc.h | 5 +++ src/game/rendering_graph_node.c | 3 +- src/pc/lua/smlua_functions_autogen.c | 32 +++++++++++++ src/pc/mods/mod.c | 6 +-- 21 files changed, 303 insertions(+), 21 deletions(-) diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index f77326d05..69771d770 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -82,7 +82,7 @@ override_allowed_functions = { "src/game/save_file.h": [ "save_file_get_", "save_file_set_flags", "save_file_clear_flags", "save_file_reload", "save_file_erase_current_backup_save", "save_file_set_star_flags", "save_file_is_cannon_unlocked", "touch_coin_score_age", "save_file_set_course_coin_score", "save_file_do_save", "save_file_remove_star_flags", "save_file_erase" ], "src/pc/lua/utils/smlua_model_utils.h": [ "smlua_model_util_get_id" ], "src/game/object_list_processor.h": [ "set_object_respawn_info_bits" ], - "src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*" ], + "src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*", "geo_get_.*_state" ], "src/pc/utils/misc.h": [ "update_all_mario_stars" ], "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", "fade_into_special_warp" ], "src/game/area.h": [ "area_get_warp_node" ], diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 833ef5e6f..222cd536f 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -88,6 +88,7 @@ override_field_invisible = { "MarioState": [ "visibleToEnemies" ], "NetworkPlayer": [ "gag", "moderator", "discordId" ], "GraphNode": [ "_guard1", "_guard2" ], + "FnGraphNode": [ "luaTokenIndex" ], "Object": [ "firstSurface" ], "ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ], } diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 7a09f0f3a..1d613c0bc 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -5788,6 +5788,18 @@ function bhv_unlock_door_star_loop() -- ... end +--- @return MarioBodyState +--- When used in a geo function, retrieve the MarioBodyState associated to the current processed object +function geo_get_body_state() + -- ... +end + +--- @return MarioState +--- When used in a geo function, retrieve the MarioState associated to the current processed object +function geo_get_mario_state() + -- ... +end + --- @return number --- Always returns zero. May have been originally used for beta trampolines function get_additive_y_vel_for_jumps() diff --git a/data/dynos.c.h b/data/dynos.c.h index 5f0314198..7d00447af 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -35,8 +35,9 @@ void dynos_generate_packs(const char* directory); // -- geos -- // void dynos_actor_override(struct Object* obj, void** aSharedChild); -void dynos_add_actor_custom(const char *filePath, const char* geoName); +void dynos_add_actor_custom(s32 modIndex, const char *filePath, const char* geoName); const void* dynos_geolayout_get(const char *name); +bool dynos_actor_get_mod_index_and_token(struct GraphNode *graphNode, u32 tokenIndex, s32 *modIndex, const char **token); // -- collisions -- // void dynos_add_collision(const char *filePath, const char* collisionName); diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 147e43a5e..c6a0fa574 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -882,8 +882,9 @@ void DynOS_Pack_AddTex(PackData* aPackData, DataNode* aTexData); // Actor Manager // -void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName); +void DynOS_Actor_AddCustom(s32 aModIndex, const SysPath &aFilename, const char *aActorName); const void *DynOS_Actor_GetLayoutFromName(const char *aActorName); +bool DynOS_Actor_GetModIndexAndToken(const GraphNode *aGraphNode, u32 aTokenIndex, s32 *outModIndex, const char **outToken); ActorGfx* DynOS_Actor_GetActorGfx(const GraphNode* aGraphNode); void DynOS_Actor_Valid(const void* aGeoref, ActorGfx& aActorGfx); void DynOS_Actor_Invalid(const void* aGeoref, s32 aPackIndex); @@ -977,7 +978,7 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool); typedef s64 (*RDConstantFunc)(const String& _Arg, bool* found); -u32 DynOS_Lua_RememberVariable(GfxData* aGfxData, void* aPtr, String& token); +u32 DynOS_Lua_RememberVariable(GfxData* aGfxData, void* aPtr, const String& token); void DynOS_Gfx_GeneratePacks(const char* directory); s64 DynOS_RecursiveDescent_Parse(const char* expr, bool* success, RDConstantFunc func); void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename); diff --git a/data/dynos_bin_geo.cpp b/data/dynos_bin_geo.cpp index dc6f75e1a..25a824d4d 100644 --- a/data/dynos_bin_geo.cpp +++ b/data/dynos_bin_geo.cpp @@ -307,7 +307,6 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLay geo_symbol_2(GEO_DISPLAY_LIST, 1); geo_symbol_3(GEO_SHADOW, 0); geo_symbol_0(GEO_RENDER_OBJ); - geo_symbol_2(GEO_ASM, 1); geo_symbol_1(GEO_BACKGROUND_COLOR, 0); geo_symbol_0(GEO_NOP_1A); geo_symbol_5(GEO_HELD_OBJECT, 2); @@ -317,6 +316,26 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLay geo_symbol_0(GEO_NOP_1F); geo_symbol_1(GEO_CULLING_RADIUS, 0); + // Geo function node + if (_Symbol == "GEO_ASM") { + s64 _Arg0 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); + const String& _Arg1 = aNode->mTokens[aTokenIndex++]; + + const void *_FunctionPtr = DynOS_Builtin_Func_GetFromName(_Arg1.begin()); + if (_FunctionPtr != NULL) { + aGfxData->mPointerList.Add(aHead + 1); + GeoLayout _Gl[] = { GEO_ASM(_Arg0, _FunctionPtr) }; + memcpy(aHead, _Gl, sizeof(_Gl)); + aHead += (sizeof(_Gl) / sizeof(_Gl[0])); + } else { + u32 _FuncIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 1, _Arg1); + GeoLayout _Gl[] = { GEO_ASM_EXT(_Arg0, _FuncIndex) }; + memcpy(aHead, _Gl, sizeof(_Gl)); + aHead += (sizeof(_Gl) / sizeof(_Gl[0])); + } + return; + } + // Switch node if (_Symbol == "GEO_SWITCH_CASE") { @@ -324,11 +343,20 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLay aSwitchNodes.Add(0); s64 _Arg0 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); - s64 _Arg1 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); - aGfxData->mPointerList.Add(aHead + 1); - GeoLayout _Gl[] = { GEO_SWITCH_CASE(_Arg0, _Arg1) }; - memcpy(aHead, _Gl, sizeof(_Gl)); - aHead += (sizeof(_Gl) / sizeof(_Gl[0])); + const String& _Arg1 = aNode->mTokens[aTokenIndex++]; + + const void *_FunctionPtr = DynOS_Builtin_Func_GetFromName(_Arg1.begin()); + if (_FunctionPtr != NULL) { + aGfxData->mPointerList.Add(aHead + 1); + GeoLayout _Gl[] = { GEO_SWITCH_CASE(_Arg0, _FunctionPtr) }; + memcpy(aHead, _Gl, sizeof(_Gl)); + aHead += (sizeof(_Gl) / sizeof(_Gl[0])); + } else { + u32 _FuncIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 1, _Arg1); + GeoLayout _Gl[] = { GEO_SWITCH_CASE_EXT(_Arg0, _FuncIndex) }; + memcpy(aHead, _Gl, sizeof(_Gl)); + aHead += (sizeof(_Gl) / sizeof(_Gl[0])); + } return; } @@ -444,6 +472,8 @@ void DynOS_Geo_Write(BinFile *aFile, GfxData *aGfxData, DataNode *aNo GeoLayout *_Head = &aNode->mData[i]; if (aGfxData->mPointerList.Find((void *) _Head) != -1) { DynOS_Pointer_Write(aFile, (const void *) (*_Head), aGfxData); + } else if (aGfxData->mLuaPointerList.Find((void *) _Head) != -1) { + DynOS_Pointer_Lua_Write(aFile, *(u32 *)_Head, aGfxData); } else { aFile->Write(*((u32 *) _Head)); } diff --git a/data/dynos_bin_utils.cpp b/data/dynos_bin_utils.cpp index c0be6817e..c9d2562c9 100644 --- a/data/dynos_bin_utils.cpp +++ b/data/dynos_bin_utils.cpp @@ -125,7 +125,7 @@ void DynOS_Gfx_Free(GfxData* aGfxData) { } } -u32 DynOS_Lua_RememberVariable(GfxData* aGfxData, void* aPtr, String& token) { +u32 DynOS_Lua_RememberVariable(GfxData* aGfxData, void* aPtr, const String& token) { // remember as lua pointer aGfxData->mLuaPointerList.Add(aPtr); diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index 3086d2316..758f46b2c 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -111,14 +111,18 @@ void dynos_actor_override(struct Object* obj, void** aSharedChild) { DynOS_Actor_Override(obj, aSharedChild); } -void dynos_add_actor_custom(const char *filePath, const char* geoName) { - DynOS_Actor_AddCustom(filePath, geoName); +void dynos_add_actor_custom(s32 modIndex, const char *filePath, const char* geoName) { + DynOS_Actor_AddCustom(modIndex, filePath, geoName); } const void* dynos_geolayout_get(const char *name) { return DynOS_Actor_GetLayoutFromName(name); } +bool dynos_actor_get_mod_index_and_token(struct GraphNode *graphNode, u32 tokenIndex, s32 *modIndex, const char **token) { + return DynOS_Actor_GetModIndexAndToken(graphNode, tokenIndex, modIndex, token); +} + // -- collisions -- // void dynos_add_collision(const char *filePath, const char* collisionName) { diff --git a/data/dynos_mgr_actor.cpp b/data/dynos_mgr_actor.cpp index caa857eb5..b0587ef25 100644 --- a/data/dynos_mgr_actor.cpp +++ b/data/dynos_mgr_actor.cpp @@ -24,7 +24,7 @@ static Array>& DynosCustomActors() { // TODO: the cleanup/refactor didn't really go as planned. // clean up the actor management code more -void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { +void DynOS_Actor_AddCustom(s32 aModIndex, const SysPath &aFilename, const char *aActorName) { const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName); u16 actorLen = strlen(aActorName); @@ -37,6 +37,7 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { free(actorName); return; } + _GfxData->mModIndex = aModIndex; void* geoLayout = (*(_GfxData->mGeoLayouts.end() - 1))->mData; if (!geoLayout) { @@ -109,6 +110,26 @@ const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) { return NULL; } +bool DynOS_Actor_GetModIndexAndToken(const GraphNode *aGraphNode, u32 aTokenIndex, s32 *outModIndex, const char **outToken) { + ActorGfx *_ActorGfx = DynOS_Actor_GetActorGfx(aGraphNode); + if (_ActorGfx) { + GfxData *_GfxData = _ActorGfx->mGfxData; + if (_GfxData) { + if (outModIndex) { + *outModIndex = _GfxData->mModIndex; + } + if (outToken) { + if (!aTokenIndex || aTokenIndex > _GfxData->mLuaTokenList.Count()) { + return false; + } + *outToken = _GfxData->mLuaTokenList[aTokenIndex - 1].begin(); // token index is 1-indexed + } + return true; + } + } + return false; +} + ActorGfx* DynOS_Actor_GetActorGfx(const GraphNode* aGraphNode) { if (aGraphNode == NULL) { return NULL; } auto& _ValidActors = DynosValidActors(); diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index b61d5ef4a..34c468a34 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -2195,6 +2195,48 @@ Behavior loop function for Star Door unlock object
+## [geo_get_body_state](#geo_get_body_state) + +### Description +When used in a geo function, retrieve the MarioBodyState associated to the current processed object + +### Lua Example +`local MarioBodyStateValue = geo_get_body_state()` + +### Parameters +- None + +### Returns +[MarioBodyState](structs.md#MarioBodyState) + +### C Prototype +`struct MarioBodyState *geo_get_body_state(void);` + +[:arrow_up_small:](#) + +
+ +## [geo_get_mario_state](#geo_get_mario_state) + +### Description +When used in a geo function, retrieve the MarioState associated to the current processed object + +### Lua Example +`local MarioStateValue = geo_get_mario_state()` + +### Parameters +- None + +### Returns +[MarioState](structs.md#MarioState) + +### C Prototype +`struct MarioState *geo_get_mario_state(void);` + +[:arrow_up_small:](#) + +
+ --- # functions from mario_step.h diff --git a/docs/lua/functions.md b/docs/lua/functions.md index a5cc268e5..0dea8f455 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1130,6 +1130,8 @@ - [bhv_toad_message_loop](functions-4.md#bhv_toad_message_loop) - [bhv_unlock_door_star_init](functions-4.md#bhv_unlock_door_star_init) - [bhv_unlock_door_star_loop](functions-4.md#bhv_unlock_door_star_loop) + - [geo_get_body_state](functions-4.md#geo_get_body_state) + - [geo_get_mario_state](functions-4.md#geo_get_mario_state)
diff --git a/include/geo_commands.h b/include/geo_commands.h index 2c058f87e..ae6392a35 100644 --- a/include/geo_commands.h +++ b/include/geo_commands.h @@ -439,4 +439,21 @@ CMD_PTR(background), \ CMD_PTR(function) + +/** + * 0x22: Create switch-case scene graph node with a custom Lua callback + */ +#define GEO_SWITCH_CASE_EXT(count, luaTokenIndex) \ + CMD_BBH(0x22, 0x00, count), \ + CMD_W(luaTokenIndex) + + +/** + * 0x23: Create dynamically generated displaylist scene graph node with a custom Lua callback + */ +#define GEO_ASM_EXT(param, luaTokenIndex) \ + CMD_BBH(0x23, 0x00, param), \ + CMD_W(luaTokenIndex) + + #endif // GEO_COMMANDS_H diff --git a/src/engine/geo_layout.c b/src/engine/geo_layout.c index d97966cba..a1927e832 100644 --- a/src/engine/geo_layout.c +++ b/src/engine/geo_layout.c @@ -45,6 +45,8 @@ GeoLayoutCommandProc GeoLayoutJumpTable[] = { geo_layout_cmd_node_culling_radius, // coop geo_layout_cmd_node_background_ext, + geo_layout_cmd_node_switch_case_ext, + geo_layout_cmd_node_generated_ext, }; struct GraphNode gObjParentGraphNode; @@ -790,6 +792,44 @@ void geo_layout_cmd_node_background_ext(void) { gGeoLayoutCommand += 0x0C << CMD_SIZE_SHIFT; } +/* + 0x22: Create switch-case scene graph node with a custom Lua callback +*/ +void geo_layout_cmd_node_switch_case_ext(void) { + struct GraphNodeSwitchCase *graphNode; + + graphNode = init_graph_node_switch_case( + gGraphNodePool, NULL, + cur_geo_cmd_s16(0x02), // num cases + 0, + (GraphNodeFunc) geo_process_lua_function, + 0 + ); + graphNode->fnNode.luaTokenIndex = cur_geo_cmd_u32(0x04); + + register_scene_graph_node(&graphNode->fnNode.node); + + gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT; +} + +/* + 0x23: Create dynamically generated displaylist scene graph node with a custom Lua callback +*/ +void geo_layout_cmd_node_generated_ext(void) { + struct GraphNodeGenerated *graphNode; + + graphNode = init_graph_node_generated( + gGraphNodePool, NULL, + (GraphNodeFunc) geo_process_lua_function, + cur_geo_cmd_s16(0x02) // parameter + ); + graphNode->fnNode.luaTokenIndex = cur_geo_cmd_u32(0x04); + + register_scene_graph_node(&graphNode->fnNode.node); + + gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT; +} + struct GraphNode *process_geo_layout(struct DynamicPool *pool, void *segptr) { // set by register_scene_graph_node when gCurGraphNodeIndex is 0 // and gCurRootGraphNode is NULL diff --git a/src/engine/geo_layout.h b/src/engine/geo_layout.h index 033919a6f..a7cbaef5b 100644 --- a/src/engine/geo_layout.h +++ b/src/engine/geo_layout.h @@ -82,6 +82,8 @@ void geo_layout_cmd_copy_view(void); void geo_layout_cmd_node_held_obj(void); void geo_layout_cmd_node_culling_radius(void); void geo_layout_cmd_node_background_ext(void); +void geo_layout_cmd_node_switch_case_ext(void); +void geo_layout_cmd_node_generated_ext(void); struct GraphNode *process_geo_layout(struct DynamicPool *a0, void *segptr); diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 3cc0f1459..992255cd4 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -653,6 +653,16 @@ struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild) { return parent; } +// A sharedChild graph node has either a parent of type GRAPH_NODE_TYPE_OBJECT or GRAPH_NODE_TYPE_OBJECT_PARENT, or no parent at all +struct GraphNode *geo_find_shared_child(struct GraphNode *graphNode) { + while (graphNode->parent && + graphNode->parent->type != GRAPH_NODE_TYPE_OBJECT && + graphNode->parent->type != GRAPH_NODE_TYPE_OBJECT_PARENT) { + graphNode = graphNode->parent; + } + return graphNode; +} + /** * Helper function for geo_call_global_function_nodes that recursively * traverses the scene graph and calls the functions of global nodes. diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index c4c5f5cfb..eaa10c352 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -79,6 +79,7 @@ struct FnGraphNode { /*0x00*/ struct GraphNode node; /*0x14*/ GraphNodeFunc func; + u32 luaTokenIndex; // reference to lua function resolved during geo_process_lua_function (1-indexed) }; /** The very root of the geo tree. Specifies the viewport. @@ -431,6 +432,7 @@ struct GraphNode *geo_add_child(struct GraphNode *parent, struct GraphNode *chil struct GraphNode* geo_remove_child_from_parent(struct GraphNode* parent, struct GraphNode* graphNode); struct GraphNode *geo_remove_child(struct GraphNode *graphNode); struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild); +struct GraphNode *geo_find_shared_child(struct GraphNode *graphNode); void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 callContext); void geo_call_global_function_nodes(struct GraphNode *graphNode, s32 callContext); diff --git a/src/game/mario_misc.c b/src/game/mario_misc.c index c6452d245..d59f16ed5 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -26,6 +26,7 @@ #include "sound_init.h" #include "pc/network/network.h" #include "pc/lua/smlua_hooks.h" +#include "pc/mods/mods.h" #define TOAD_STAR_1_REQUIREMENT gBehaviorValues.ToadStar1Requirement #define TOAD_STAR_2_REQUIREMENT gBehaviorValues.ToadStar2Requirement @@ -346,12 +347,12 @@ static u8 geo_get_processing_object_index(void) { return (index >= MAX_PLAYERS) ? 0 : index; } -static struct MarioState* geo_get_mario_state(void) { +struct MarioState *geo_get_mario_state(void) { u8 index = geo_get_processing_object_index(); return &gMarioStates[index]; } -static struct MarioBodyState* geo_get_body_state(void) { +struct MarioBodyState *geo_get_body_state(void) { u8 index = geo_get_processing_object_index(); return &gBodyStates[index]; } @@ -838,3 +839,63 @@ Gfx* geo_mario_cap_display_list(s32 callContext, struct GraphNode* node, UNUSED asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (character->capEnemyLayer << 8); return gfx; } + +Gfx *geo_process_lua_function(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) { + extern s16 gMatStackIndex; + lua_State *L = gLuaState; + + // Do nothing outside of geo_process + if (callContext != GEO_CONTEXT_RENDER) { + return NULL; + } + + // Check node type + if (!node || !(node->type & GRAPH_NODE_TYPE_FUNCTIONAL)) { + return NULL; + } + struct FnGraphNode *fnNode = (struct FnGraphNode *) node; + struct GraphNode *sharedChild = geo_find_shared_child(node); + + // Retrieve mod index and function name + s32 modIndex = -1; + const char *funcStr = NULL; + if (!dynos_actor_get_mod_index_and_token(sharedChild, fnNode->luaTokenIndex, &modIndex, &funcStr)) { + if (modIndex == -1) { + LOG_ERROR("Could not find graph node mod index"); + } else if (funcStr == NULL) { + LOG_ERROR("Could not find graph node function name"); + } + return NULL; + } + + // Retrieve function ref + gSmLuaConvertSuccess = true; + LuaFunction funcRef = smlua_get_function_mod_variable(modIndex, funcStr); + if (!gSmLuaConvertSuccess) { + gSmLuaConvertSuccess = true; + funcRef = smlua_get_any_function_mod_variable(funcStr); + } + if (!gSmLuaConvertSuccess || funcRef == 0) { + LOG_LUA("Failed to call lua function, could not find lua function '%s'", funcStr); + return NULL; + } + + // Get the mod + if (modIndex >= gActiveMods.entryCount) { + LOG_LUA("Failed to call lua function, could not find mod"); + return NULL; + } + struct Mod *mod = gActiveMods.entries[modIndex]; + + // Push the callback, the graph node and the current matrix stack index + lua_rawgeti(L, LUA_REGISTRYINDEX, funcRef); + smlua_push_object(L, LOT_GRAPHNODE, node); + lua_pushinteger(L, gMatStackIndex); + + // Call the callback + if (0 != smlua_call_hook(L, 2, 0, 0, mod)) { + LOG_LUA("Failed to call the function callback: '%s'", funcStr); + } + + return NULL; +} diff --git a/src/game/mario_misc.h b/src/game/mario_misc.h index e5e85ad21..cf436a200 100644 --- a/src/game/mario_misc.h +++ b/src/game/mario_misc.h @@ -18,6 +18,10 @@ void bhv_toad_message_loop(void); void bhv_unlock_door_star_init(void); /* |description|Behavior loop function for Star Door unlock object|descriptionEnd| */ void bhv_unlock_door_star_loop(void); +/* |description|When used in a geo function, retrieve the MarioState associated to the current processed object|descriptionEnd| */ +struct MarioState *geo_get_mario_state(void); +/* |description|When used in a geo function, retrieve the MarioBodyState associated to the current processed object|descriptionEnd| */ +struct MarioBodyState *geo_get_body_state(void); Gfx *geo_mirror_mario_set_alpha(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); Gfx *geo_switch_mario_stand_run(s32 callContext, struct GraphNode *node, UNUSED Mat4 *mtx); Gfx *geo_switch_mario_eyes(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); @@ -33,5 +37,6 @@ Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat Gfx *geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); Gfx* geo_mario_set_player_colors(s32 callContext, struct GraphNode* node, UNUSED Mat4* c); Gfx* geo_mario_cap_display_list(s32 callContext, struct GraphNode* node, UNUSED Mat4* c); +Gfx *geo_process_lua_function(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); #endif // MARIO_MISC_H diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 61b33e405..da6656d7a 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -800,8 +800,7 @@ static void geo_process_display_list(struct GraphNodeDisplayList *node) { */ static void geo_process_generated_list(struct GraphNodeGenerated *node) { if (node->fnNode.func != NULL) { - Gfx *list = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, - (struct DynamicPool *) gMatStack[gMatStackIndex]); + Gfx *list = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, gMatStack[gMatStackIndex]); if (list != NULL) { geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(list), node->fnNode.node.flags >> 8); diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index f7a664c54..940f44a7a 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -17977,6 +17977,36 @@ int smlua_func_bhv_unlock_door_star_loop(UNUSED lua_State* L) { return 1; } +int smlua_func_geo_get_body_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", "geo_get_body_state", 0, top); + return 0; + } + + + smlua_push_object(L, LOT_MARIOBODYSTATE, geo_get_body_state()); + + return 1; +} + +int smlua_func_geo_get_mario_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", "geo_get_mario_state", 0, top); + return 0; + } + + + smlua_push_object(L, LOT_MARIOSTATE, geo_get_mario_state()); + + return 1; +} + ////////////////// // mario_step.h // ////////////////// @@ -32992,6 +33022,8 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "bhv_toad_message_loop", smlua_func_bhv_toad_message_loop); smlua_bind_function(L, "bhv_unlock_door_star_init", smlua_func_bhv_unlock_door_star_init); smlua_bind_function(L, "bhv_unlock_door_star_loop", smlua_func_bhv_unlock_door_star_loop); + smlua_bind_function(L, "geo_get_body_state", smlua_func_geo_get_body_state); + smlua_bind_function(L, "geo_get_mario_state", smlua_func_geo_get_mario_state); // mario_step.h smlua_bind_function(L, "get_additive_y_vel_for_jumps", smlua_func_get_additive_y_vel_for_jumps); diff --git a/src/pc/mods/mod.c b/src/pc/mods/mod.c index 3ee2fb8b1..5c9a39a0d 100644 --- a/src/pc/mods/mod.c +++ b/src/pc/mods/mod.c @@ -21,7 +21,7 @@ size_t mod_get_lua_size(struct Mod* mod) { return size; } -static void mod_activate_bin(struct ModFile* file) { +static void mod_activate_bin(struct Mod* mod, struct ModFile* file) { // copy geo name char geoName[64] = { 0 }; if (snprintf(geoName, 63, "%s", path_basename(file->relativePath)) < 0) { @@ -41,7 +41,7 @@ static void mod_activate_bin(struct ModFile* file) { // Add to custom actors LOG_INFO("Activating DynOS bin: '%s', '%s'", file->cachedPath, geoName); - dynos_add_actor_custom(file->cachedPath, geoName); + dynos_add_actor_custom(mod->index, file->cachedPath, geoName); } static void mod_activate_col(struct ModFile* file) { @@ -148,7 +148,7 @@ void mod_activate(struct Mod* mod) { } if (str_ends_with(file->relativePath, ".bin")) { - mod_activate_bin(file); + mod_activate_bin(mod, file); } if (str_ends_with(file->relativePath, ".col")) { mod_activate_col(file);