diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 8c2707453..9c56ac32b 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1767,6 +1767,10 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::SameLine(); UIWidgets::EnhancementCombobox("gCosmetics.DefaultColorScheme", colorSchemes, COLORSCHEME_N64); UIWidgets::EnhancementCheckbox("Advanced Mode", "gCosmetics.AdvancedMode"); + UIWidgets::InsertHelpHoverText( + "Some cosmetic options may not apply if you have any mods that provide custom models for the cosmetic option.\n\n" + "For example, if you have custom Link model, then the Link's Hair color option will most likely not apply." + ); if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) { if (ImGui::Button("Lock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { for (auto& [id, cosmeticOption] : cosmeticOptions) { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1199a7e99..ad57d1ca5 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1569,6 +1569,11 @@ extern "C" Gfx* ResourceMgr_LoadGfxByName(const char* path) return (Gfx*)&res->Instructions[0]; } +extern "C" uint8_t ResourceMgr_FileIsCustomByName(const char* path) { + auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); + return res->GetInitData()->IsCustom; +} + typedef struct { int index; Gfx instruction; @@ -1600,6 +1605,11 @@ extern "C" void ResourceMgr_PatchGfxByName(const char* path, const char* patchNa // index /= 2; // } + // Do not patch custom assets as they most likely do not have the same instructions as authentic assets + if (res->GetInitData()->IsCustom) { + return; + } + Gfx* gfx = (Gfx*)&res->Instructions[index]; if (!originalGfx.contains(path) || !originalGfx[path].contains(patchName)) { @@ -1616,6 +1626,11 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch auto res = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource(path)); + // Do not patch custom assets as they most likely do not have the same instructions as authentic assets + if (res->GetInitData()->IsCustom) { + return; + } + Gfx* destinationGfx = (Gfx*)&res->Instructions[destinationIndex]; Gfx sourceGfx = res->Instructions[sourceIndex]; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 82659dbc4..e00cfecd5 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -101,6 +101,7 @@ AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path); char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc); Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc); Gfx* ResourceMgr_LoadGfxByName(const char* path); +uint8_t ResourceMgr_FileIsCustomByName(const char* path); void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index a5fc12299..a71d2b8e3 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -532,6 +532,8 @@ void DrawEnhancementsMenu() { " - Small keys: Small silver chest\n" " - Boss keys: Vanilla size and texture\n" " - Skulltula Tokens: Small skulltula chest\n" + "\n" + "NOTE: Textures will not apply if you are using a mod pack with a custom chest model." ); if (CVarGetInteger("gChestSizeAndTextureMatchesContents", CSMC_DISABLED) != CSMC_DISABLED) { UIWidgets::PaddedEnhancementCheckbox("Chests of Agony", "gChestSizeDependsStoneOfAgony", true, false); diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 1e2c4d6cd..9e8705c33 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -88,6 +88,7 @@ Gfx gKeyTreasureChestChestFrontDL[128] = {0}; Gfx gChristmasRedTreasureChestChestFrontDL[128] = {0}; Gfx gChristmasGreenTreasureChestChestFrontDL[128] = {0}; u8 hasCreatedRandoChestTextures = 0; +u8 hasCustomChestDLs = 0; u8 hasChristmasChestTexturesAvailable = 0; void EnBox_SetupAction(EnBox* this, EnBoxActionFunc actionFunc) { @@ -690,7 +691,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } // Change texture - if (!isVanilla && (csmc == CSMC_BOTH || csmc == CSMC_TEXTURE)) { + if (!isVanilla && hasCreatedRandoChestTextures && !hasCustomChestDLs && (csmc == CSMC_BOTH || csmc == CSMC_TEXTURE)) { switch (getItemCategory) { case ITEM_CATEGORY_MAJOR: this->boxBodyDL = gGoldTreasureChestChestFrontDL; @@ -725,7 +726,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } } - if (CVarGetInteger("gLetItSnow", 0) && hasChristmasChestTexturesAvailable) { + if (CVarGetInteger("gLetItSnow", 0) && hasChristmasChestTexturesAvailable && hasCreatedRandoChestTextures && !hasCustomChestDLs) { if (this->dyna.actor.scale.x == 0.01f) { this->boxBodyDL = gChristmasRedTreasureChestChestFrontDL; this->boxLidDL = gChristmasRedTreasureChestChestSideAndLidDL; @@ -767,7 +768,18 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } void EnBox_CreateExtraChestTextures() { + // Don't patch textures for custom chest models, as they do not import textures the exact same way as vanilla chests + // OTRTODO: Make it so model packs can provide a unique DL per chest type, instead of us copying the brown chest and attempting to patch + if (ResourceMgr_FileIsCustomByName(gTreasureChestChestFrontDL) || + ResourceMgr_FileIsCustomByName(gTreasureChestChestSideAndLidDL)) { + hasCustomChestDLs = 1; + return; + } + + hasCustomChestDLs = 0; + if (hasCreatedRandoChestTextures) return; + Gfx gTreasureChestChestTextures[] = { gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, gSkullTreasureChestFrontTex), gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, gSkullTreasureChestSideAndTopTex),