From d6e243c4a762a989373e5e1379c13aea72298185 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Tue, 4 Mar 2025 15:09:09 +1000 Subject: [PATCH] add obj_get_model_id_extended, remember regular model ids --- autogen/lua_definitions/functions.lua | 7 ++++ data/dynos_mgr_models.cpp | 11 +++-- docs/lua/functions-6.md | 23 +++++++++++ docs/lua/functions.md | 1 + include/model_ids.h | 2 + src/pc/lua/smlua_functions_autogen.c | 18 ++++++++ src/pc/lua/utils/smlua_model_utils.c | 59 ++++++++++++++++++++++++++- src/pc/lua/utils/smlua_model_utils.h | 3 ++ src/pc/lua/utils/smlua_obj_utils.c | 11 +++-- src/pc/lua/utils/smlua_obj_utils.h | 2 + 10 files changed, 130 insertions(+), 7 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 08651ea69..ef0fbccbe 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -10076,6 +10076,13 @@ function obj_get_first_with_behavior_id_and_field_s32(behaviorId, fieldIndex, va -- ... end +--- @param o Object +--- @return ModelExtendedId +--- Returns an object's extended model id +function obj_get_model_id_extended(o) + -- ... +end + --- @param o Object --- @param behaviorId BehaviorId --- @return Object diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp index 9ceec81cd..90386fac2 100644 --- a/data/dynos_mgr_models.cpp +++ b/data/dynos_mgr_models.cpp @@ -6,10 +6,9 @@ extern "C" { #include "engine/geo_layout.h" #include "engine/graph_node.h" #include "model_ids.h" +#include "pc/lua/utils/smlua_model_utils.h" } -#define VANILLA_ID_END 255 - enum ModelLoadType { MLT_GEO, MLT_DL, @@ -58,7 +57,7 @@ void DynOS_Model_Dump() { } } -struct GraphNode* DynOS_Model_LoadCommon(u32* aId, enum ModelPool aModelPool, void* aAsset, u8 aLayer, struct GraphNode* aGraphNode, bool aDeDuplicate, enum ModelLoadType mlt) { +static struct GraphNode* DynOS_Model_LoadCommonInternal(u32* aId, enum ModelPool aModelPool, void* aAsset, u8 aLayer, struct GraphNode* aGraphNode, bool aDeDuplicate, enum ModelLoadType mlt) { // sanity check pool if (aModelPool >= MODEL_POOL_MAX) { return NULL; } @@ -124,6 +123,12 @@ struct GraphNode* DynOS_Model_LoadCommon(u32* aId, enum ModelPool aModelPool, vo return node; } +static struct GraphNode* DynOS_Model_LoadCommon(u32* aId, enum ModelPool aModelPool, void* aAsset, u8 aLayer, struct GraphNode* aGraphNode, bool aDeDuplicate, enum ModelLoadType mlt) { + struct GraphNode* node = DynOS_Model_LoadCommonInternal(aId, aModelPool, aAsset, aLayer, aGraphNode, aDeDuplicate, mlt); + smlua_model_util_register_model_id(*aId, aAsset); + return node; +} + struct GraphNode* DynOS_Model_LoadGeo(u32* aId, enum ModelPool aModelPool, void* aAsset, bool aDeDuplicate) { return DynOS_Model_LoadCommon(aId, aModelPool, aAsset, 0, NULL, aDeDuplicate, MLT_GEO); } diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index ec51fa095..13e0bf7f3 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -2215,6 +2215,29 @@ Gets the first object loaded with `behaviorId` and object signed 32-bit integer
+## [obj_get_model_id_extended](#obj_get_model_id_extended) + +### Description +Returns an object's extended model id + +### Lua Example +`local enumValue = obj_get_model_id_extended(o)` + +### Parameters +| Field | Type | +| ----- | ---- | +| o | [Object](structs.md#Object) | + +### Returns +[enum ModelExtendedId](constants.md#enum-ModelExtendedId) + +### C Prototype +`enum ModelExtendedId obj_get_model_id_extended(struct Object *o);` + +[:arrow_up_small:](#) + +
+ ## [obj_get_nearest_object_with_behavior_id](#obj_get_nearest_object_with_behavior_id) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index fe1ab79c3..fd8d8b7b0 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1847,6 +1847,7 @@ - [obj_get_first_with_behavior_id](functions-6.md#obj_get_first_with_behavior_id) - [obj_get_first_with_behavior_id_and_field_f32](functions-6.md#obj_get_first_with_behavior_id_and_field_f32) - [obj_get_first_with_behavior_id_and_field_s32](functions-6.md#obj_get_first_with_behavior_id_and_field_s32) + - [obj_get_model_id_extended](functions-6.md#obj_get_model_id_extended) - [obj_get_nearest_object_with_behavior_id](functions-6.md#obj_get_nearest_object_with_behavior_id) - [obj_get_next](functions-6.md#obj_get_next) - [obj_get_next_with_same_behavior_id](functions-6.md#obj_get_next_with_same_behavior_id) diff --git a/include/model_ids.h b/include/model_ids.h index e7e900e2f..8cd85e7fc 100644 --- a/include/model_ids.h +++ b/include/model_ids.h @@ -19,6 +19,8 @@ #define COIN_FORMATION_FLAG_ARROW (1 << 2) #define COIN_FORMATION_FLAG_FLYING (1 << 4) +#define VANILLA_ID_END 255 + #define MODEL_NONE 0x00 /* Global models that are loaded for every level */ diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index a64cf1ac2..f3b781eb3 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -30547,6 +30547,23 @@ int smlua_func_obj_get_first_with_behavior_id_and_field_s32(lua_State* L) { return 1; } +int smlua_func_obj_get_model_id_extended(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", "obj_get_model_id_extended", 1, top); + return 0; + } + + struct Object* o = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_get_model_id_extended"); return 0; } + + lua_pushinteger(L, obj_get_model_id_extended(o)); + + return 1; +} + int smlua_func_obj_get_nearest_object_with_behavior_id(lua_State* L) { if (L == NULL) { return 0; } @@ -33857,6 +33874,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "obj_get_first_with_behavior_id", smlua_func_obj_get_first_with_behavior_id); smlua_bind_function(L, "obj_get_first_with_behavior_id_and_field_f32", smlua_func_obj_get_first_with_behavior_id_and_field_f32); smlua_bind_function(L, "obj_get_first_with_behavior_id_and_field_s32", smlua_func_obj_get_first_with_behavior_id_and_field_s32); + smlua_bind_function(L, "obj_get_model_id_extended", smlua_func_obj_get_model_id_extended); smlua_bind_function(L, "obj_get_nearest_object_with_behavior_id", smlua_func_obj_get_nearest_object_with_behavior_id); smlua_bind_function(L, "obj_get_next", smlua_func_obj_get_next); smlua_bind_function(L, "obj_get_next_with_same_behavior_id", smlua_func_obj_get_next_with_same_behavior_id); diff --git a/src/pc/lua/utils/smlua_model_utils.c b/src/pc/lua/utils/smlua_model_utils.c index c94375d70..759f4d227 100644 --- a/src/pc/lua/utils/smlua_model_utils.c +++ b/src/pc/lua/utils/smlua_model_utils.c @@ -486,8 +486,10 @@ void smlua_model_util_store_in_slot(u32 slot, const char* name) { dynos_model_overwrite_slot(slot, loadedId); } +// Takes an extended model id, loads the model, and returns the regular model id u16 smlua_model_util_load(enum ModelExtendedId extId) { - if ((u32)extId >= (u32)E_MODEL_MAX + (u32)sCustomModelsCount) { extId = E_MODEL_ERROR_MODEL; } + if (extId == E_MODEL_NONE) { return MODEL_NONE; } + if (!extId || (u32)extId >= (u32)E_MODEL_MAX + (u32)sCustomModelsCount) { extId = E_MODEL_ERROR_MODEL; } struct ModelUtilsInfo* info = (extId < E_MODEL_MAX) ? &sModels[extId] @@ -502,6 +504,61 @@ u16 smlua_model_util_load(enum ModelExtendedId extId) { return (u16)id; } +// Links the regular model id created by DynOS to our models list +void smlua_model_util_register_model_id(u32 id, const void *asset) { + if (id < VANILLA_ID_END) { + for (u32 i = 0; i < E_MODEL_MAX; i++) { + struct ModelUtilsInfo* m = &sModels[i]; + if (m->asset == asset) { + m->loadedId = id; + return; + } + } + } else { + for (u32 i = 0; i < sCustomModelsCount; i++) { + struct ModelUtilsInfo* m = &sCustomModels[i]; + if (m->asset == asset) { + m->loadedId = id; + return; + } + } + } +} + +// Translates an extended model id to a regular model id +u16 smlua_model_util_ext_id_to_id(enum ModelExtendedId extId) { + if (extId == E_MODEL_NONE) { return MODEL_NONE; } + if ((u32)extId >= (u32)E_MODEL_MAX + (u32)sCustomModelsCount) { return MODEL_ERROR_MODEL; } + + struct ModelUtilsInfo* info = (extId < E_MODEL_MAX) + ? &sModels[extId] + : &sCustomModels[extId - E_MODEL_MAX]; + return info->loadedId != UNLOADED_ID ? info->loadedId : MODEL_ERROR_MODEL; +} + +// Translates a regular model id to an extended model id +enum ModelExtendedId smlua_model_util_id_to_ext_id(u16 id) { + if (!id) { return E_MODEL_NONE; } + + // Check built-in models + for (u32 i = 0; i < E_MODEL_MAX; i++) { + struct ModelUtilsInfo* m = &sModels[i]; + if (m->loadedId == id) { + return m->extId; + } + } + + // Check custom models + for (u32 i = 0; i < sCustomModelsCount; i++) { + struct ModelUtilsInfo* m = &sCustomModels[i]; + if (m->loadedId == id) { + return m->extId; + } + } + + return E_MODEL_ERROR_MODEL; +} + enum ModelExtendedId smlua_model_util_get_id(const char* name) { // Find geolayout const void* asset = dynos_geolayout_get(name); diff --git a/src/pc/lua/utils/smlua_model_utils.h b/src/pc/lua/utils/smlua_model_utils.h index 13e06f68a..3e3a955d2 100644 --- a/src/pc/lua/utils/smlua_model_utils.h +++ b/src/pc/lua/utils/smlua_model_utils.h @@ -399,6 +399,9 @@ void smlua_model_util_initialize(void); void smlua_model_util_clear(void); void smlua_model_util_store_in_slot(u32 slot, const char* name); u16 smlua_model_util_load(enum ModelExtendedId extId); +void smlua_model_util_register_model_id(u32 id, const void *asset); +u16 smlua_model_util_ext_id_to_id(enum ModelExtendedId extId); +enum ModelExtendedId smlua_model_util_id_to_ext_id(u16 id); /* |description|Gets the extended model ID for the `name` of a `GeoLayout`|descriptionEnd| */ enum ModelExtendedId smlua_model_util_get_id(const char* name); diff --git a/src/pc/lua/utils/smlua_obj_utils.c b/src/pc/lua/utils/smlua_obj_utils.c index 3f9e63db3..ca651591e 100644 --- a/src/pc/lua/utils/smlua_obj_utils.c +++ b/src/pc/lua/utils/smlua_obj_utils.c @@ -92,9 +92,14 @@ s32 obj_has_behavior_id(struct Object *o, enum BehaviorId behaviorId) { s32 obj_has_model_extended(struct Object *o, enum ModelExtendedId modelId) { if (!o) { return 0; } - u16 slot = smlua_model_util_load(modelId); - struct GraphNode *model = dynos_model_get_geo(slot); - return o->header.gfx.sharedChild == model; + if (!o->header.gfx.sharedChild && modelId == E_MODEL_NONE) { return 1; } + return dynos_model_get_id_from_graph_node(o->header.gfx.sharedChild) == smlua_model_util_ext_id_to_id(modelId); +} + +enum ModelExtendedId obj_get_model_id_extended(struct Object *o) { + if (!o) { return E_MODEL_NONE; } + if (!o->header.gfx.sharedChild) { return E_MODEL_NONE; } + return smlua_model_util_id_to_ext_id(dynos_model_get_id_from_graph_node(o->header.gfx.sharedChild)); } void obj_set_model_extended(struct Object *o, enum ModelExtendedId modelId) { diff --git a/src/pc/lua/utils/smlua_obj_utils.h b/src/pc/lua/utils/smlua_obj_utils.h index a36ed4d9b..c833ffe2b 100644 --- a/src/pc/lua/utils/smlua_obj_utils.h +++ b/src/pc/lua/utils/smlua_obj_utils.h @@ -20,6 +20,8 @@ struct Object* spawn_non_sync_object(enum BehaviorId behaviorId, enum ModelExten s32 obj_has_behavior_id(struct Object *o, enum BehaviorId behaviorId); /* |description|Checks if an object's model is equal to `modelId`|descriptionEnd| */ s32 obj_has_model_extended(struct Object *o, enum ModelExtendedId modelId); +/* |description|Returns an object's extended model id|descriptionEnd| */ +enum ModelExtendedId obj_get_model_id_extended(struct Object *o); /* |description|Sets an object's model to `modelId`|descriptionEnd| */ void obj_set_model_extended(struct Object *o, enum ModelExtendedId modelId);