diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL new file mode 100644 index 000000000..939042daa --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 new file mode 100644 index 000000000..8c320d243 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 new file mode 100644 index 000000000..0990859d5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 new file mode 100644 index 000000000..37e6186e9 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 new file mode 100644 index 000000000..4360eedc5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull new file mode 100644 index 000000000..cedf6351d --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material new file mode 100644 index 000000000..4dc39e811 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material new file mode 100644 index 000000000..6941bb55f --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/noise_tex b/soh/assets/custom/objects/object_mystery_item/noise_tex new file mode 100644 index 000000000..aaf4e331f Binary files /dev/null and b/soh/assets/custom/objects/object_mystery_item/noise_tex differ diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index 58fed005f..e8c947d0e 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -77,6 +77,9 @@ static const ALIGN_ASSET(2) char gBossSoulSkullDL[] = dgBossSoulSkullDL; #define dgFishingPoleGiDL "__OTR__objects/object_gi_fishing_pole/gFishingPoleGiDL" static const ALIGN_ASSET(2) char gFishingPoleGiDL[] = dgFishingPoleGiDL; +#define dgMysteryItemDL "__OTR__objects/object_mystery_item/gMysteryItemDL" +static const ALIGN_ASSET(2) char gMysteryItemDL[] = dgMysteryItemDL; + // overlays #define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx" static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx; diff --git a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp index 7430152ab..cfa0a2a2d 100644 --- a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp +++ b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp @@ -46,10 +46,18 @@ template<> struct is_char_type: public boost::true_type {}; #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_SAME std::is_same +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_SAME is_same +#endif + template -inline typename boost::enable_if_< +inline typename BOOST_ENABLE_IF< is_char_type::value_type>::value && - is_same::iterator_category, std::random_access_iterator_tag>::value, + BOOST_IS_SAME::iterator_category, std::random_access_iterator_tag>::value, std::size_t>::type hash_range_32( uint32_t seed, It first, It last ) { @@ -114,4 +122,7 @@ std::size_t>::type } // namespace hash_detail } // namespace boost +#undef BOOST_ENABLE_IF +#undef BOOST_IS_SAME + #endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP diff --git a/soh/include/boost_custom/container_hash/hash_32.hpp b/soh/include/boost_custom/container_hash/hash_32.hpp index 4b955c43a..eaf459a34 100644 --- a/soh/include/boost_custom/container_hash/hash_32.hpp +++ b/soh/include/boost_custom/container_hash/hash_32.hpp @@ -23,6 +23,18 @@ #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_INTEGRAL hash_detail::is_integral +#define BOOST_IS_UNSIGNED is_unsigned +#define BOOST_MAKE_UNSIGNED make_unsigned +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_INTEGRAL boost::is_integral +#define BOOST_IS_UNSIGNED boost::is_unsigned +#define BOOST_MAKE_UNSIGNED boost::make_unsigned +#endif + namespace boost { @@ -36,7 +48,7 @@ namespace boost { template sizeof(uint32_t)), - bool is_unsigned = boost::is_unsigned::value, + bool is_unsigned = BOOST_IS_UNSIGNED::value, std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT, std::size_t type_bits = sizeof(T) * CHAR_BIT> struct hash_integral_impl_32; @@ -53,7 +65,7 @@ namespace boost { static uint32_t fn( T v ) { - typedef typename boost::make_unsigned::type U; + typedef typename BOOST_MAKE_UNSIGNED::type U; if( v >= 0 ) { @@ -97,7 +109,7 @@ namespace boost } // namespace hash_detail template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T v ) { return hash_detail::hash_integral_impl_32::fn( v ); @@ -106,7 +118,7 @@ namespace boost // contiguous ranges (string, vector, array) #if BOOST_VERSION_HAS_HASH_RANGE template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T const& v ) { return boost::hash_range_32( v.data(), v.data() + v.size() ); @@ -168,5 +180,9 @@ namespace boost } // namespace boost #undef BOOST_HASH_CHAR_TRAITS +#undef BOOST_ENABLE_IF +#undef BOOST_IS_INTEGRAL +#undef BOOST_IS_UNSIGNED +#undef BOOST_MAKE_UNSIGNED #endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP diff --git a/soh/include/boost_custom/container_hash/version.hpp b/soh/include/boost_custom/container_hash/version.hpp index 22ad6634c..3863b507c 100644 --- a/soh/include/boost_custom/container_hash/version.hpp +++ b/soh/include/boost_custom/container_hash/version.hpp @@ -6,4 +6,6 @@ #define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81) +#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84) + #endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP diff --git a/soh/include/variables.h b/soh/include/variables.h index 9fd6b7247..2c226f2c6 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -172,7 +172,8 @@ extern "C" extern u8 gWalkSpeedToggle2; extern f32 iceTrapScale; extern f32 triforcePieceScale; - + extern f32 mysteryItemScale; + extern const s16 D_8014A6C0[]; #define gTatumsPerBeat (D_8014A6C0[1]) extern const AudioContextInitSizes D_8014A6C4; diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index b932d24cc..4badd8279 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -323,6 +323,7 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4(0, 60, 100, 255), false, true, false), COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 1f2888809..fabefebe8 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -163,7 +163,7 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("GravediggingTourFix"), CVAR_ENHANCEMENT("DekuNutUpgradeFix"), CVAR_ENHANCEMENT("NaviTextFix"), - CVAR_ENHANCEMENT("AnubixFix"), + CVAR_ENHANCEMENT("AnubisFix"), CVAR_ENHANCEMENT("CrouchStabHammerFix"), CVAR_ENHANCEMENT("CrouchStabFix"), CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), @@ -702,7 +702,7 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), @@ -828,7 +828,7 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 338bfdb33..f35567b83 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -296,7 +296,7 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get if (triforcePieceScale < 0.0001f) { triforcePieceScale += 0.00003f; } - + // Animation. When not the completed triforce, create delay before showing the piece to bypass interpolation. // If the completed triforce, make it grow slowly. if (current != required) { @@ -323,6 +323,29 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get } else if (current == required && triforcePieceScale > 0.00008f) { gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gTriforcePieceCompletedDL); } + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry) { + Color_RGB8 color = { 0, 60, 100 }; + if (CVarGetInteger(CVAR_COSMETIC("World.MysteryItem.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("World.MysteryItem.Value"), color); + } + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255); + gSPGrayscale(POLY_XLU_DISP++, true); + + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gMysteryItemDL); + + gSPGrayscale(POLY_XLU_DISP++, false); + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 51300f3a6..ea56e6e32 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -21,6 +21,10 @@ void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry); + +#define GET_ITEM_MYSTERY \ + { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, Randomizer_DrawMysteryItem } #ifdef __cplusplus }; #endif diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 6f5820952..231d5e411 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2466,8 +2466,16 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf); RandomizerGet shopItemGet = ctx->GetItemLocation(rc)->GetPlacedRandomizerGet(); CustomMessage shopItemName; - if (mysterious) { - shopItemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM].GetHintMessage(); + if (mysterious|| CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + if (randomizerInf >= RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1 && randomizerInf <= RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8) { + shopItemName = { + "Mysterious Item", + "Mysteriösen Gegenstand", + "Objet Mystérieux" + }; + } else { + shopItemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM].GetHintMessage(); + } // TODO: This should eventually be replaced with a full fledged trick model & trick name system } else if (shopItemGet == RG_ICE_TRAP) { shopItemGet = ctx->overrides[rc].LooksLike(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 1e9fec263..acbc3ad7f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -10,6 +10,8 @@ #include "context.h" #include #include "soh/Enhancements/randomizer/randomizer_check_objects.h" +#include "soh/Enhancements/randomizer/randomizer_check_tracker.h" +#include "soh/Enhancements/randomizer/randomizer_tricks.h" #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" #include "../custom-message/CustomMessageTypes.h" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 772d4d747..ace7781be 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -144,8 +144,8 @@ RandomizerCheckArea currentArea = RCAREA_INVALID; OSContPad* trackerButtonsPressed; std::unordered_map checkNameOverrides; -bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheck check); -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); +bool ShouldShowCheck(RandomizerCheck rc); +bool ShouldHideArea(RandomizerCheckArea rcArea); void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0); bool CompareChecks(RandomizerCheck, RandomizerCheck); bool CheckByArea(RandomizerCheckArea); @@ -214,6 +214,7 @@ Color_RGBA8 Color_Saved_Extra = { 0, 185, 0, 255 }; // Green std::vector buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT, BTN_L, BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; +static ImGuiTextFilter checkSearch; void DefaultCheckData(RandomizerCheck rc) { gSaveContext.checkTrackerData[rc].status = RCSHOW_UNCHECKED; @@ -943,9 +944,9 @@ void CheckTrackerWindow::DrawElement() { optCollapseAll = true; } ImGui::SameLine(); - static ImGuiTextFilter checkSearch; if (ImGui::Button("Clear")) { checkSearch.Clear(); + doAreaScroll = true; } UIWidgets::Tooltip("Clear the search field"); checkSearch.Draw(); @@ -983,6 +984,8 @@ void CheckTrackerWindow::DrawElement() { Color_RGBA8 extraColor; std::string stemp; + bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); + for (auto& [rcArea, checks] : checksByArea) { RandomizerCheckArea thisArea = currentArea; @@ -996,7 +999,7 @@ void CheckTrackerWindow::DrawElement() { previousShowHidden = showHidden; doAreaScroll = true; } - if (shouldHideArea(checkSearch, checksByArea, rcArea) || + if ((shouldHideFilteredAreas && ShouldHideArea(rcArea)) || (!showHidden && ((hideComplete && thisAreaFullyChecked) || (hideIncomplete && !thisAreaFullyChecked))) ) { doDraw = false; @@ -1056,7 +1059,7 @@ void CheckTrackerWindow::DrawElement() { doAreaScroll = false; } for (auto rc : checks) { - if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rc) && passesTextFilter(checkSearch, rc)) { + if (doDraw && isThisAreaSpoiled && ShouldShowCheck(rc)) { DrawLocation(rc); } } @@ -1076,14 +1079,12 @@ void CheckTrackerWindow::DrawElement() { } } -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { - bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); - if (!shouldHideFilteredAreas) { +bool ShouldHideArea(RandomizerCheckArea rcArea) { + if (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { return false; } - for (auto check : checksByArea[rcArea]) { - if (IsVisibleInCheckTracker(check) && passesTextFilter(checkSearch, check)) { + if (ShouldShowCheck(check)) { return false; } } @@ -1091,8 +1092,10 @@ bool shouldHideArea(ImGuiTextFilter& checkSearch, std::mapGetArea()).c_str()) || checkSearch.PassFilter(Rando::StaticData::GetLocation(check)->GetShortName().c_str()) ); @@ -1241,7 +1244,7 @@ void LoadSettings() { fishsanityAgeSplit = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT); } -bool IsVisibleInCheckTracker(RandomizerCheck rc) { +bool IsCheckShuffled(RandomizerCheckObject rcObj) { Rando::Location* loc = Rando::StaticData::GetLocation(rc); if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { return @@ -1255,7 +1258,7 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) { loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsMQ() || loc->GetQuest() == RCQUEST_VANILLA && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsVanilla() ) && - (loc->GetRCType() != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && loc->GetActorParams() > 0x03))) && + (loc->GetRCType() != RCTYPE_SHOP || (showShops && loc->GetActorParams() > 0x03)) && (loc->GetRandomizerCheck() != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) && (rc != RC_TRIFORCE_COMPLETED || !hideTriforceCompleted) && (rc != RC_GIFT_FROM_SAGES || !IS_RANDO) && @@ -1304,6 +1307,10 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) { return false; } +bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { + return IsCheckShuffled(rcObj) || (rcObj.rcType == RCTYPE_SKULL_TOKEN && alwaysShowGS) || (rcObj.rcType == RCTYPE_SHOP && (showShops && (!hideShopRightChecks))); +} + void UpdateInventoryChecks() { //For all the areas with maps, if you have one, spoil the area for (auto [scene, area] : DungeonRCAreasBySceneID) { @@ -1494,6 +1501,8 @@ void DrawLocation(RandomizerCheck rc) { //Draw the extra info txt = ""; + bool mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && OTRGlobals::Instance->gRandomizer->merchantPrices.contains(rcObj.rc); + if (checkData.hintItem != 0) { // TODO hints } else if (status != RCSHOW_UNCHECKED) { @@ -1516,16 +1525,16 @@ void DrawLocation(RandomizerCheck rc) { case RCSHOW_IDENTIFIED: case RCSHOW_SEEN: if (IS_RANDO) { - if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) { + if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP && !mystery) { if (status == RCSHOW_IDENTIFIED) { txt = OTRGlobals::Instance->gRandoContext->overrides[rc].GetTrickName().GetForLanguage(gSaveContext.language); } else { txt = Rando::StaticData::RetrieveItem(OTRGlobals::Instance->gRandoContext->overrides[rc].LooksLike()).GetName().GetForLanguage(gSaveContext.language); } - } else { + } else if (!mystery) { txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language); } - if (status == RCSHOW_IDENTIFIED) { + if (!IsVisibleInCheckTracker(rcObj) && status == RCSHOW_IDENTIFIED && !mystery) { txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rc].price); } } else { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 9362bccc6..576a09cc7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -47,6 +47,7 @@ void DefaultCheckData(RandomizerCheck rc); void Teardown(); void UpdateAllOrdering(); bool IsVisibleInCheckTracker(RandomizerCheck rc); +bool IsCheckShuffled(RandomizerCheck check); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 41878bcce..bf248d0e0 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -86,6 +86,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" +#include "Enhancements/randomizer/draw.h" #include // Resource Types/Factories @@ -1808,7 +1809,7 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch } Gfx* destinationGfx = (Gfx*)&res->Instructions[destinationIndex]; - Gfx sourceGfx = res->Instructions[sourceIndex]; + Gfx sourceGfx = *(Gfx*)&res->Instructions[sourceIndex]; if (!originalGfx.contains(path) || !originalGfx[path].contains(patchName)) { originalGfx[path][patchName] = { @@ -2444,6 +2445,14 @@ extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck( return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck); } +extern "C" bool Randomizer_IsCheckShuffled(RandomizerCheck randomizerCheck) { + return CheckTracker::IsCheckShuffled(RandomizerCheckObjects::GetAllRCObjects().find(randomizerCheck)->second); +} + +extern "C" GetItemEntry GetItemMystery() { + return { ITEM_NONE_FE, 0, 0, 0, 0, 0, 0, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, NULL, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem }; +} + extern "C" void Randomizer_GenerateSeed() { std::string seed = ""; if (OTRGlobals::Instance->gRandoContext->IsSpoilerLoaded()) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 2e566bbd2..3ea1b9c23 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -181,6 +181,8 @@ GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId); RandomizerInf Randomizer_GetRandomizerInfFromCheck(RandomizerCheck randomizerCheck); +bool Randomizer_IsCheckShuffled(RandomizerCheck check); +GetItemEntry GetItemMystery(); ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); void Randomizer_GenerateSeed(); uint8_t Randomizer_IsSeedGenerated(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 7ac3e1e20..a85c69a40 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -656,7 +656,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", CVAR_ENHANCEMENT("MweepSpeed"), 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", CVAR_ENHANCEMENT("ClimbSpeed"), 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", CVAR_ENHANCEMENT("FasterBlockPush"), 0, 5, "", 0, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 4, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", CVAR_ENHANCEMENT("FasterHeavyBlockLift"), false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", CVAR_ENHANCEMENT("FastDrops"), true, false); @@ -1290,7 +1290,7 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", CVAR_ENHANCEMENT("NaviTextFix"), true, false); UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubixFix"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubisFix"), true, false); UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); if (UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", CVAR_ENHANCEMENT("CrouchStabHammerFix"), true, false)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { @@ -2086,6 +2086,11 @@ void DrawRandomizerMenu() { "Play unique fanfares when obtaining quest items " "(medallions/stones/songs). Note that these fanfares are longer than usual." ); + UIWidgets::PaddedEnhancementCheckbox("Mysterious Shuffled Items", CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), true, false); + UIWidgets::Tooltip( + "Displays a \"Mystery Item\" model in place of any freestanding/GS/shop items that were shuffled, " + "and replaces item names for them and scrubs and merchants, regardless of hint settings, " + "so you never know what you're getting."); ImGui::EndMenu(); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 8e30f462a..f286830e6 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1361,7 +1361,23 @@ static const Vtx customDropVtx[] = { * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). */ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { - if (this->actor.params == ITEM00_BOMBCHU) { + if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { + RandomizerCheck randoCheck = + Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; + + if (randoCheck != RC_UNKNOWN_CHECK) { + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; + } + + f32 mtxScale = 16.0f; + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); + } else if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -1441,7 +1457,24 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) { * Draw Function used for the Piece of Heart type of En_Item00. */ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { - s32 pad; + if (IS_RANDO) { + RandomizerCheck randoCheck = + Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; + + if (randoCheck != RC_UNKNOWN_CHECK) { + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; + } + + f32 mtxScale = 16.0f; + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); + } else { + s32 pad; OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 934b9486d..658e96394 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1436,64 +1436,62 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te return displayListHead; } -void Inventory_SwapAgeEquipment(void) { +void Rando_Inventory_SwapAgeEquipment(void) { s16 i; u16 shieldEquipValue; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (i != 0) { - gSaveContext.childEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; } else { gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; } if (i != 0) { - gSaveContext.childEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } - // When becoming adult, remove swordless flag since we'll get master sword - // (Unless Master Sword is shuffled) - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; - if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.adultEquips.equipment)) { - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; - } else { - gSaveContext.equips.buttonItems[0] = ITEM_NONE; - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + // When becoming adult, remove swordless flag since we'll get master sword + // This gets set back appropriately later in the case of master sword shuffle + Flags_UnsetInfTable(INFTABLE_SWORDLESS); + + // This section sets up the equipment on the first time going adult. + // On master sword shuffle the check for the B button is insufficient, and so checking the equipment is completely zero-ed is needed + // (Could just always use `gSaveContext.adultEquips.equipment == 0` for rando?) + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && ((IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) || (gSaveContext.adultEquips.equipment == 0))) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { gSaveContext.equips.buttonItems[1] = ITEM_NUT; gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; } else { - gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE; + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; } gSaveContext.equips.buttonItems[2] = ITEM_BOMB; gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; - gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | - (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | - (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // In Master Sword Shuffle we want to override the equip of the master sword from the vanilla code + // First check we have the Master sword in our inventory, and if not, then unequip if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] == ITEM_NONE) { + !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; + Flags_SetInfTable(INFTABLE_SWORDLESS); } - // Set the dpad to nothing gSaveContext.equips.buttonItems[4] = ITEM_NONE; gSaveContext.equips.buttonItems[5] = ITEM_NONE; @@ -1505,25 +1503,25 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; } else { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.adultEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.adultEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - // In Rando, when switching to adult for the second+ time, if a sword was not previously - // equiped in MS shuffle, then we need to set the swordless flag again - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && + // In Master Sword Shuffle we want to set the swordless flag if no item is on the B button + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.equips.buttonItems[0] == ITEM_NONE) { Flags_SetInfTable(INFTABLE_SWORDLESS); } @@ -1531,90 +1529,43 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; } } else { - // When becoming child, set swordless flag if player doesn't have kokiri sword - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } - - // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. - // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; - } for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; if (i != 0) { - gSaveContext.adultEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; - // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) { + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - // Equips kokiri sword in the inventory screen only if kokiri sword exists in inventory and a sword has been equipped already - if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) && !Flags_GetInfTable(INFTABLE_SWORDLESS)) { - gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } - } else if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; - - if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; - } - - if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && - (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || - ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && - (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); - gSaveContext.equips.buttonItems[i] = - gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; - } - } - - // In Rando, when switching to child from a swordless adult, and child Link previously had a - // sword equiped, then we need to unset the swordless flag to match - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] != ITEM_NONE) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } else if (IS_RANDO && Randomizer_GetSettingValue(RSK_STARTING_AGE) == RO_AGE_ADULT) { - /*If in rando and starting age is adult, childEquips is not initialized and buttonItems[0] - will be ITEM_NONE. When changing age from adult -> child, reset equips to "default" - (only kokiri tunic/boots equipped, no sword, no C-button items, no D-Pad items). - When becoming child, set swordless flag if player doesn't have kokiri sword - Only in rando to keep swordless link bugs in vanilla*/ - if (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + } + // In Rando we need an extra case to handle starting as adult. We can use the fact that the childEquips will be uninitialised (i.e. 0) at this point + else if (gSaveContext.childEquips.equipment == 0) { //zero out items for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { @@ -1629,20 +1580,147 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) && - (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { + // When becoming child in rando, set swordless flag and clear B button if player doesn't have kokiri sword + // Otherwise, equip sword and unset flag + if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI)) { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; Flags_SetInfTable(INFTABLE_SWORDLESS); - if (gSaveContext.childEquips.equipment == 0) { - // force equip kokiri tunic and boots in scenario gSaveContext.childEquips.equipment is uninitialized - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - gSaveContext.equips.equipment |= (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); - } + } else { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI; + Flags_UnsetInfTable(INFTABLE_SWORDLESS); } } - CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 0); + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; - if (shieldEquipValue != 0) { + if (shieldEquipValue) { + shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; + if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { + gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; + } + } +} + +void Inventory_SwapAgeEquipment(void) { + s16 i; + u16 shieldEquipValue; + + // Mod Enhancments can utilise the rando flow path + if (IS_RANDO || CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) { + Rando_Inventory_SwapAgeEquipment(); + CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 0); + return; + } + + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + if (i != 0) { + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; + } else { + gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; + } + + if (i != 0) { + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + + if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { + gSaveContext.equips.buttonItems[1] = ITEM_NUT; + gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; + } else { + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; + } + + gSaveContext.equips.buttonItems[2] = ITEM_BOMB; + gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; + gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; + gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; + gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // Set the dpad to nothing + gSaveContext.equips.buttonItems[4] = ITEM_NONE; + gSaveContext.equips.buttonItems[5] = ITEM_NONE; + gSaveContext.equips.buttonItems[6] = ITEM_NONE; + gSaveContext.equips.buttonItems[7] = ITEM_NONE; + gSaveContext.equips.cButtonSlots[3] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[4] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[5] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; + } + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + + if (i != 0) { + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); + } + } + + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; + if (shieldEquipValue) { shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 4af2e9f87..2e06e8975 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -2089,6 +2089,8 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { } if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { GetItemEntry getItemEntry = GET_ITEM_NONE; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_BARINADE)) + getItemEntry = GetItemMystery(); switch (this->actor.params) { case DEMO_EFFECT_JEWEL_KOKIRI: diff --git a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c index 0b1a2b0b7..a26f5a08b 100644 --- a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c +++ b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c @@ -116,7 +116,7 @@ void func_809B27D8(EnAnubiceFire* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); this->cylinder.base.atFlags &= 0xFFE9; this->cylinder.base.atFlags |= 8; - this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubixFix"), 0) ? 0x800 : 2; + this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubisFix"), 0) ? 0x800 : 2; this->unk_15A = 30; this->actor.params = 1; this->actor.velocity.x *= -1.0f; diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 8b3195d72..26116664a 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -487,12 +487,46 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { } if (this) {} func_8002ED80(&this->actor, play, 0); + if (IS_RANDO) { + GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; + switch (this->type) { + case EXITEM_BOMB_BAG_BOWLING: + case EXITEM_BOMB_BAG_COUNTER: + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE)) + ? GetItemMystery() + : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); + break; + case EXITEM_BOMBCHUS_BOWLING: + case EXITEM_BOMBCHUS_COUNTER: + randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); + break; + case EXITEM_BULLET_BAG: + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LW_TARGET_IN_WOODS)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + break; + } + + if (randoGetItem.getItemId != GI_NONE) { + EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); + GetItemEntry_Draw(play, randoGetItem); + return; + } + } + GetItem_Draw(play, this->giDrawId); } void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); - GetItem_Draw(play, GID_HEART_PIECE); + + if (IS_RANDO) { + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); + EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); + GetItemEntry_Draw(play, randoGetItem); + } else { + GetItem_Draw(play, GID_HEART_PIECE); + } } void EnExItem_DrawMagic(EnExItem* this, PlayState* play, s16 magicIndex) { diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 11c29227f..0382735a3 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -1286,8 +1286,8 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) { this->basePrice = shopItemIdentity.itemPrice; this->giDrawId = getItemEntry.gid; - // Correct the rotation for spiritual stones - if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) { + // Correct the rotation for spiritual stones, but only if mysterious shuffle isn't on, else it's obvious what's there in shops + if (!CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE)) { this->actor.shape.rot.y = this->actor.shape.rot.y + 20000; } } @@ -1332,7 +1332,8 @@ void EnGirlA_Draw(Actor* thisx, PlayState* play) { if (this->actor.params == SI_RANDOMIZED_ITEM) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && this->actor.params == SI_RANDOMIZED_ITEM) ? GetItemMystery() : + Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); EnItem00_CustomItemsParticles(&this->actor, play, getItemEntry); GetItemEntry_Draw(play, getItemEntry); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 170eed16e..bf0e4951d 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -155,6 +155,50 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (this->actionFunc != func_80AFB950) { func_8002ED80(&this->actor, play, 0); func_8002EBCC(&this->actor, play, 0); - GetItem_Draw(play, GID_SKULL_TOKEN_2); + if (!IS_RANDO) { + GetItem_Draw(play, GID_SKULL_TOKEN_2); + } else { + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + getItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_SKULL_TOKEN); + EnItem00_CustomItemsParticles(&this->actor, play, getItem); + if (getItem.itemId != ITEM_SKULL_TOKEN) { + f32 mtxScale = 1.5f; + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + } + GetItemEntry_Draw(play, getItem); + } + } +} + +void EnSi_Reset() { + textId = 0xB4; + giveItemId = ITEM_SKULL_TOKEN; +} + +void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); + getItemId = getItem.getItemId; + if (getItemId == RG_ICE_TRAP) { + textId = 0xF8; + } else { + textId = getItem.textId; + giveItemId = getItem.itemId; + } + player->getItemEntry = getItem; +} + +void Randomizer_GiveSkullReward(EnSi* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (getItem.modIndex == MOD_NONE) { + // RANDOTOD: Move this into Item_Give() or some other more central location + if (getItem.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } + Item_Give(play, giveItemId); + } else if (getItem.modIndex == MOD_RANDOMIZER) { + Randomizer_Item_Give(play, getItem); } } diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index 5015a3908..02656e119 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -93,18 +93,23 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { actorIt = actorIt->next; } - if (flag) { - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); + if (IS_RANDO) { + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + GetItemEntry_Draw(play, (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_HEART_CONTAINER_2)); } else { - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); + if (flag) { + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); + } else { + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); + } } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index 796b157a3..d27893c3a 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -206,12 +206,42 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { if (play->actorCtx.lensActive) { func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); + + if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { + RandomizerCheck check = RC_MAX; + GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); //TODO Rando: add mysterious shuffle when chest minigame keys get shuffled + EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); + if (randoGetItem.itemId != ITEM_NONE) { + GetItemEntry_Draw(play, randoGetItem); + return; + } + } + GetItem_Draw(play, this->giDrawId); } } void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; + s32 type = this->actor.params & 0xFF; + + if (IS_RANDO) { + GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; + if (type == ITEM_ETC_ARROW_FIRE) { + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_SUN)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); + } else if (type == ITEM_ETC_LETTER) { + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_UNDERWATER_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + } + + EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); + + if (randoGetItem.itemId != ITEM_NONE) { + func_8002EBCC(&this->actor, play, 0); + func_8002ED80(&this->actor, play, 0); + GetItemEntry_Draw(play, randoGetItem); + return; + } + } func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index 358a2efe7..cf83b730a 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -212,7 +212,7 @@ void ItemOcarina_Draw(Actor* thisx, PlayState* play) { func_8002ED80(thisx, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_HF_OCARINA_OF_TIME_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); GetItemEntry_Draw(play, randoGetItem); return;