diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 7a775769..1123b142 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7688,6 +7688,14 @@ function obj_set_billboard(obj) -- ... end +--- @param obj Object +--- @param index integer +--- @param modelID integer +--- @return nil +function obj_set_character_model(obj, index, modelID) + -- ... +end + --- @param obj Object --- @return nil function obj_set_cylboard(obj) diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index c2e6fda6..84741cfe 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -5961,6 +5961,28 @@
+## [obj_set_character_model](#obj_set_character_model) + +### Lua Example +`obj_set_character_model(obj, index, modelID)` + +### Parameters +| Field | Type | +| ----- | ---- | +| obj | [Object](structs.md#Object) | +| index | `integer` | +| modelID | `integer` | + +### Returns +- None + +### C Prototype +`void obj_set_character_model(struct Object* obj, u16 index, s32 modelID);` + +[:arrow_up_small:](#) + +
+ ## [obj_set_cylboard](#obj_set_cylboard) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 959a6cfc..f095b482 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1443,6 +1443,7 @@ - [obj_set_angle](functions-4.md#obj_set_angle) - [obj_set_behavior](functions-4.md#obj_set_behavior) - [obj_set_billboard](functions-4.md#obj_set_billboard) + - [obj_set_character_model](functions-4.md#obj_set_character_model) - [obj_set_cylboard](functions-4.md#obj_set_cylboard) - [obj_set_face_angle](functions-4.md#obj_set_face_angle) - [obj_set_face_angle_to_move_angle](functions-4.md#obj_set_face_angle_to_move_angle) diff --git a/lang/Czech.ini b/lang/Czech.ini index fb097b7e..0e32ec03 100644 --- a/lang/Czech.ini +++ b/lang/Czech.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Výběr souboru" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Globální modely hráčů" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/Dutch.ini b/lang/Dutch.ini index 9d037640..469d96a0 100644 --- a/lang/Dutch.ini +++ b/lang/Dutch.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Bestand selecteren" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Globale spelermodellen" [HOST_MESSAGE] INFO_TITLE = "INFORMATIE" diff --git a/lang/English.ini b/lang/English.ini index 2da41c11..29ce7bd5 100644 --- a/lang/English.ini +++ b/lang/English.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "File Select" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Global Player Models" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/French.ini b/lang/French.ini index 8f1a2395..9e30ec14 100644 --- a/lang/French.ini +++ b/lang/French.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Sélection de fichier" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Modèles de joueurs mondiaux" [HOST_MESSAGE] INFO_TITLE = "INFORMATIONS" diff --git a/lang/German.ini b/lang/German.ini index 4417d479..c767964b 100644 --- a/lang/German.ini +++ b/lang/German.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Dateiauswahl" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Globale Spielermodelle" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/Italian.ini b/lang/Italian.ini index 0038fc9d..31b17c6c 100644 --- a/lang/Italian.ini +++ b/lang/Italian.ini @@ -152,6 +152,7 @@ FILE_SELECT_THEME = "Selezione file" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Modelli di giocatore globali" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/Polish.ini b/lang/Polish.ini index 37783358..8ee7ad52 100644 --- a/lang/Polish.ini +++ b/lang/Polish.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Wybór Pliku" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Globalne modele graczy" [HOST_MESSAGE] INFO_TITLE = "INFORMACJE" diff --git a/lang/Portuguese.ini b/lang/Portuguese.ini index 1542f260..635a4738 100644 --- a/lang/Portuguese.ini +++ b/lang/Portuguese.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Escolha de arquivo" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Modelos de jogador global" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/Russian.ini b/lang/Russian.ini index 8b8446d1..0dab0f23 100644 --- a/lang/Russian.ini +++ b/lang/Russian.ini @@ -153,6 +153,7 @@ FILE_SELECT_THEME = "Выбор файла" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Глобальные модели игроков" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/lang/Spanish.ini b/lang/Spanish.ini index 2c5f700f..4fcae9da 100644 --- a/lang/Spanish.ini +++ b/lang/Spanish.ini @@ -154,6 +154,7 @@ FILE_SELECT_THEME = "Selección de archivo" [DYNOS] DYNOS = "DYNOS" +GLOBAL_PLAYER_MODELS = "Modelos de jugador global" [HOST_MESSAGE] INFO_TITLE = "INFO" diff --git a/src/game/mario.c b/src/game/mario.c index 08575e68..bed16a32 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2369,7 +2369,7 @@ void init_single_mario(struct MarioState* m) { u8 modelIndex = gNetworkPlayers[playerIndex].overrideModelIndex; if (modelIndex >= CT_MAX) { modelIndex = 0; } m->character = &gCharacters[modelIndex]; - obj_set_model(m->marioObj, m->character->modelId); + obj_set_character_model(m->marioObj, m->playerIndex, m->character->modelId); } void init_mario(void) { diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index a6654c92..49012137 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -1441,6 +1441,14 @@ void obj_set_model(struct Object* obj, s32 modelID) { smlua_call_event_hooks_object_model_param(HOOK_OBJECT_SET_MODEL, obj, modelID); } +void obj_set_character_model(struct Object* obj, u16 index, s32 modelID) { + obj->header.gfx.sharedChild = dynos_model_get_geo(modelID); + if (configGlobalPlayerModels || index == 0) { + dynos_actor_override((void*)&obj->header.gfx.sharedChild); + } + smlua_call_event_hooks_object_model_param(HOOK_OBJECT_SET_MODEL, obj, modelID); +} + void mario_set_flag(s32 flag) { gMarioStates[0].flags |= flag; } diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index 5934ce93..1804de3d 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -175,6 +175,7 @@ void cur_obj_get_thrown_or_placed(f32 forwardVel, f32 velY, s32 thrownAction); void cur_obj_get_dropped(void); void cur_obj_set_model(s32 modelID); void obj_set_model(struct Object* obj, s32 modelID); +void obj_set_character_model(struct Object* obj, u16 index, s32 modelID); void mario_set_flag(s32 flag); s32 cur_obj_clear_interact_status_flag(s32 flag); void obj_mark_for_deletion(struct Object *obj); diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 71eca46f..b35d1eb1 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -165,6 +165,7 @@ unsigned int configDjuiTheme = DJUI_THEME_DARK; bool configDjuiThemeCenter = true; unsigned int configDjuiScale = 0; bool configCoopCompatibility = false; +bool configGlobalPlayerModels = true; char configLastVersion[MAX_CONFIG_STRING] = SM64COOPDX_VERSION; static const struct ConfigOption options[] = { @@ -262,6 +263,7 @@ static const struct ConfigOption options[] = { {.name = "coop_custom_palette_cap", .type = CONFIG_TYPE_COLOR , .colorValue = &configCustomPalette.parts[CAP]}, {.name = "coop_stay_in_level_after_star", .type = CONFIG_TYPE_UINT , .uintValue = &configStayInLevelAfterStar}, {.name = "coop_compatibility", .type = CONFIG_TYPE_BOOL , .boolValue = &configCoopCompatibility}, + {.name = "coopdx_global_player_models", .type = CONFIG_TYPE_BOOL , .boolValue = &configGlobalPlayerModels}, {.name = "disable_popups", .type = CONFIG_TYPE_BOOL , .boolValue = &configDisablePopups}, {.name = "lua_profiler", .type = CONFIG_TYPE_BOOL , .boolValue = &configLuaProfiler}, #ifdef DEVELOPMENT diff --git a/src/pc/configfile.h b/src/pc/configfile.h index c9cef7eb..85b05885 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -122,6 +122,7 @@ extern unsigned int configDjuiTheme; extern bool configDjuiThemeCenter; extern unsigned int configDjuiScale; extern bool configCoopCompatibility; +extern bool configGlobalPlayerModels; extern char configLastVersion[]; void enable_queued_mods(); diff --git a/src/pc/djui/djui_panel_dynos.c b/src/pc/djui/djui_panel_dynos.c index 084df260..4fe037a7 100644 --- a/src/pc/djui/djui_panel_dynos.c +++ b/src/pc/djui/djui_panel_dynos.c @@ -14,6 +14,12 @@ static void djui_panel_dynos_apply(struct DjuiBase* caller) { dynos_pack_set_enabled(caller->tag, caller->bTag); } +static void djui_panel_dynos_global_player_models(UNUSED struct DjuiBase* caller) { + for (s32 i = 0; i < MAX_PLAYERS; i++) { + network_player_update_model(i); + } +} + static void djui_panel_dynos_refresh(UNUSED struct DjuiBase* base) { dynos_gfx_init(); dynos_packs_init(); @@ -46,6 +52,12 @@ void djui_panel_dynos_create(struct DjuiBase* caller) { } djui_paginated_calculate_height(paginated); + struct DjuiRect* space = djui_rect_create(body); + djui_base_set_size_type(&space->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&space->base, (DJUI_DEFAULT_PANEL_WIDTH * (configDjuiThemeCenter ? DJUI_THEME_CENTERED_WIDTH : 1)) - 32, 1); + djui_base_set_color(&space->base, 220, 220, 220, 255); + + djui_checkbox_create(body, DLANG(DYNOS, GLOBAL_PLAYER_MODELS), &configGlobalPlayerModels, djui_panel_dynos_global_player_models); if (gNetworkType == NT_NONE) { struct DjuiRect* rect1 = djui_rect_container_create(body, 64); { @@ -56,7 +68,7 @@ void djui_panel_dynos_create(struct DjuiBase* caller) { djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back); } - panel->bodySize.value = paginated->base.height.value + 16 + 64; + panel->bodySize.value = paginated->base.height.value + 16 + 64 + 64; } djui_panel_add(caller, panel, NULL); diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index d2a91fc7..c8807bf0 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -25818,6 +25818,28 @@ int smlua_func_obj_set_billboard(lua_State* L) { return 1; } +int smlua_func_obj_set_character_model(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_set_character_model", 3, top); + return 0; + } + + struct Object* obj = (struct Object*)smlua_to_cobject(L, 1, LOT_OBJECT); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "obj_set_character_model"); return 0; } + u16 index = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "obj_set_character_model"); return 0; } + s32 modelID = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "obj_set_character_model"); return 0; } + + extern void obj_set_character_model(struct Object* obj, u16 index, s32 modelID); + obj_set_character_model(obj, index, modelID); + + return 1; +} + /* int smlua_func_obj_set_collision_data(lua_State* L) { if (L == NULL) { return 0; } @@ -32855,6 +32877,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "obj_set_angle", smlua_func_obj_set_angle); smlua_bind_function(L, "obj_set_behavior", smlua_func_obj_set_behavior); smlua_bind_function(L, "obj_set_billboard", smlua_func_obj_set_billboard); + smlua_bind_function(L, "obj_set_character_model", smlua_func_obj_set_character_model); //smlua_bind_function(L, "obj_set_collision_data", smlua_func_obj_set_collision_data); <--- UNIMPLEMENTED smlua_bind_function(L, "obj_set_cylboard", smlua_func_obj_set_cylboard); smlua_bind_function(L, "obj_set_face_angle", smlua_func_obj_set_face_angle); diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 1b29b843..fcc696b6 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -39,7 +39,7 @@ void network_player_update_model(u8 localIndex) { m->character = &gCharacters[index]; if (m->marioObj == NULL) { return; } - obj_set_model(m->marioObj, m->character->modelId); + obj_set_character_model(m->marioObj, m->playerIndex, m->character->modelId); } bool network_player_any_connected(void) {