From b3d51441eb8759f607a9448c535c46f6a9cddecd Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 17:17:08 -0700 Subject: [PATCH] Rando Enhancement: Mysterious Shuffled Items (#3227) * Add rando enhancement "Mysterious Shuffled Items", which obfuscates shuffled freestanding/drawn-in-world items (PoH, tokens, shop items) with a custom question mark model (thanks Hato), and uses the "mysterious item" functionality of `GetMerchantMessage` for everything that supports it, regardless of hint status on generation. * Reverted back to rando enhancement, but added condition for Mysterious Shuffle not being on for the gem rotation fix to apply. * First attempt at changing to fake GetItemEntry instead of directly calling the mystery draw function. Needs more work. * Updated CVar to reflect CVar rework values. Added `IsCheckShuffled` as preliminary function for checking *only* if a check is shuffled, not necessarily if it is just visible on the tracker. This accounts for the difference between tokensanity and "Always Show GS On Tracker", where you don't want to obfuscate the latter. * Bit of cleanup. * Cross-platform building edits. If anyone has a better idea of how to handle this fake GIE, I'm all ears. * Update to CVar macros. * Fix freestanding item gives. Fix mysterious item model colors. * Fix bombchu bowling mystery. * Remove bowling bomchus check obfuscation (unused, removed in v3). --- .../object_mystery_item/gMysteryItemDL | 16 + .../object_mystery_item/gMysteryItemDL_tri_0 | 56 +++ .../object_mystery_item/gMysteryItemDL_tri_1 | 120 +++++ .../object_mystery_item/gMysteryItemDL_vtx_0 | 119 +++++ .../object_mystery_item/gMysteryItemDL_vtx_1 | 416 ++++++++++++++++++ .../gMysteryItemDL_vtx_cull | 10 + ...yItemDL_f3dlite_mysteryItem_light_material | 21 + ...MysteryItemDL_f3dlite_mysteryItem_material | 21 + .../objects/object_mystery_item/noise_tex | Bin 0 -> 1116 bytes soh/assets/soh_assets.h | 3 + soh/include/variables.h | 3 +- .../cosmetics/CosmeticsEditor.cpp | 1 + soh/soh/Enhancements/randomizer/draw.cpp | 25 +- soh/soh/Enhancements/randomizer/draw.h | 4 + .../Enhancements/randomizer/randomizer.cpp | 20 +- soh/soh/Enhancements/randomizer/randomizer.h | 1 + .../randomizer/randomizer_check_tracker.cpp | 19 +- .../randomizer/randomizer_check_tracker.h | 1 + soh/soh/OTRGlobals.cpp | 9 + soh/soh/OTRGlobals.h | 2 + soh/soh/SohMenuBar.cpp | 5 + soh/src/code/z_en_item00.c | 28 +- .../actors/ovl_Demo_Effect/z_demo_effect.c | 3 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 11 +- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 3 +- .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 4 +- .../ovl_Item_Etcetera/z_item_etcetera.c | 7 +- .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 2 +- 29 files changed, 896 insertions(+), 41 deletions(-) create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material create mode 100644 soh/assets/custom/objects/object_mystery_item/noise_tex 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 0000000000..939042daaf --- /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 0000000000..8c320d2436 --- /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 0000000000..0990859d5a --- /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 0000000000..37e6186e94 --- /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 0000000000..4360eedc50 --- /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 0000000000..cedf6351d1 --- /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 0000000000..4dc39e8113 --- /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 0000000000..6941bb55fd --- /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 0000000000000000000000000000000000000000..aaf4e331f15f797a3b1122b58c57b3767e66bc0f GIT binary patch literal 1116 zcma)5S&rmH5G^FcIk*X5eDlKxBf5LKx?JVw&9uYY}ZlKyY|id266pZ|L)_-3^t z{^e>VIz`u(`^dKQ%g2w`bDu%x{^r%I8%i=wg`pMy&>oT`wvAwTeqNf)RT*l1cl(+W z4O3wm5FDBuCz%Uiv0TQ&*Cj#VNy!7F8h~R}KQ9uTqZsmTyW<5x_pt+H9l4&R zNV*$EuA#8o9Vc?s{bsv;)Pm5GMBTP6z|sQ5v2V)EX1(5QHV?AIOLmqzz`$u>%G@KX zAm1U#Q1`b#-cdY`0zWyHA&UB`uvJOq1z;j%s@!gUchADQtBSnLBiuZ{ObIeINsvAl zKp>GPf~X&wGE1T`oqzfLxlOSLfeJL;gpe$uxkXczdF&C0F2DWpa%!p~b}e0&RKxLI z%T231NzwpnD1Z9&={oddS76r=ISB@l@A&(Ji`>A~6jZ+b`Tf)mbH67OcwTj)5Scc{ zK!pLxobvMFI`+$@k4zv-0AY+25fE@S6z$W{&&H?oX}(_jP*+sLjS^qu9wmr;+rj%{ zAEy-|@BH@CVH4;m%+kORMa{#BXIWla6lGO6!#wp(?ire4hv`1{96uqtA;^bi)3$9t zo$9i#W2i_9OzJvM;xx4+nwI?IFm%JTj73}=LclXD2+J}FLmcRYNZGH3zUij9O&r(N zIC{GkOwTb52m2bcW%RfiySf=qM4ckHqqfwB78L>#iUN&&l-#mE4Q;=iy9hjP)*G6p zcAUU-vK4wNFT$)pja`3!_q^mt=2&vXvP9&Xrb8$zFlv{%J+_yZm#3OgWf__(%K$o# zDT@+s;Ci{tRaQ>d>(W(+JVHPr6kC2^iS&+v`RR%Lt01bUX&g>t6B|4yh?4GjP~1K+ zRyjYNyVUUyr+Hf5EKR78{fMr0WJ>e{hl 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/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 4fbe489d2d..7a970b8950 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -248,7 +248,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) { @@ -275,5 +275,28 @@ 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 d9134573d4..8c152a4f9f 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -16,6 +16,10 @@ void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(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 f5c522ddc0..107e23e83d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -5412,12 +5412,20 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf); RandomizerGet shopItemGet = this->itemLocations[rc].rgID; std::array shopItemName; - if (mysterious) { - shopItemName = { - "mysterious item", - "mysteriösen Gegenstand", - "objet mystérieux" - }; + 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 = { + "mysterious item", + "mysteriösen Gegenstand", + "objet mystérieux" + }; + } // TODO: This should eventually be replaced with a full fledged trick model & trick name system } else if (shopItemGet == RG_ICE_TRAP) { shopItemGet = this->itemLocations[rc].fakeRgID; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a726cecdee..ce8f5c45be 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -9,6 +9,7 @@ #include #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" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 4ca8c79937..a53b838f30 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1223,7 +1223,7 @@ void LoadSettings() { } } -bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { +bool IsCheckShuffled(RandomizerCheckObject rcObj) { if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { return (rcObj.rcArea != RCAREA_INVALID) && // don't show Invalid locations @@ -1236,7 +1236,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) || rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ) && - (rcObj.rcType != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && rcObj.actorParams > 0x03))) && + (rcObj.rcType != RCTYPE_SHOP || (showShops && rcObj.actorParams > 0x03)) && (rcObj.rcType != RCTYPE_SCRUB || showScrubs || rcObj.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || // The 3 scrubs that are always randomized @@ -1245,7 +1245,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { ) && (rcObj.rcType != RCTYPE_MERCHANT || showMerchants) && (rcObj.rcType != RCTYPE_OCARINA || showOcarinas) && - (rcObj.rcType != RCTYPE_SKULL_TOKEN || alwaysShowGS || + (rcObj.rcType != RCTYPE_SKULL_TOKEN || (showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) || (showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea)) ) && @@ -1265,6 +1265,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { (rcObj.rcType != RCTYPE_BOSS_KEY || showBossKeysanity) && (rcObj.rcType != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) && (rcObj.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || show100SkullReward) && + (rcObj.rc != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) && (rcObj.rcType != RCTYPE_GF_KEY && rcObj.rc != RC_GF_GERUDO_MEMBERSHIP_CARD || (showGerudoCard && rcObj.rc == RC_GF_GERUDO_MEMBERSHIP_CARD) || (fortressNormal && showGerudoFortressKeys && rcObj.rcType == RCTYPE_GF_KEY) || @@ -1280,6 +1281,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { 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) { @@ -1444,6 +1449,8 @@ void DrawLocation(RandomizerCheckObject rcObj) { //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) { @@ -1466,16 +1473,16 @@ void DrawLocation(RandomizerCheckObject rcObj) { case RCSHOW_IDENTIFIED: case RCSHOW_SEEN: if (IS_RANDO) { - if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP) { + if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP && !mystery) { if (status == RCSHOW_IDENTIFIED) { txt = gSaveContext.itemLocations[rcObj.rc].get.trickName; } else { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.fakeRgID][gSaveContext.language]; } - } else { + } else if (!mystery) { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.rgID][gSaveContext.language]; } - if (status == RCSHOW_IDENTIFIED) { + if (!IsVisibleInCheckTracker(rcObj) && status == RCSHOW_IDENTIFIED && !mystery) { txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rcObj.rc].price); } } else { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 216da367fc..be1ae441c0 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(RandomizerCheckObject rcObj); +bool IsCheckShuffled(RandomizerCheckObject 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 b61bb65cc8..518e9c1f32 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -84,6 +84,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" +#include "Enhancements/randomizer/draw.h" #include // Resource Types/Factories @@ -2437,6 +2438,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 }; +} + CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) { s16 giid; if (player->getItemEntry.objectId != OBJECT_INVALID) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 73cb58d976..e0b5c7a381 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -179,6 +179,8 @@ GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorPar GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId); +bool Randomizer_IsCheckShuffled(RandomizerCheck check); +GetItemEntry GetItemMystery(); ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); int CustomMessage_RetrieveIfExists(PlayState* play); void Overlay_DisplayText(float duration, const char* text); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c396de7389..35274e5ac5 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1972,6 +1972,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 db344d39e9..7728177160 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1366,17 +1366,19 @@ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { 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); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + 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 = 10.67f; + + f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); @@ -1460,17 +1462,19 @@ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { 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); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + 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, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else { s32 pad; 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 149c176c70..edab23ae80 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 @@ -2088,7 +2088,8 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { return; } if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_BARINADE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); this->getItem.drawId = getItemEntry.gid; func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); 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 a3a196e314..b2d23984cc 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 @@ -515,14 +515,17 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { switch (this->type) { case EXITEM_BOMB_BAG_BOWLING: case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); + 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 = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + 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; } @@ -540,8 +543,8 @@ void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); + 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 { 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 11c29227fc..0382735a3c 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 185a39c515..98e8f41163 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 @@ -214,7 +214,8 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (!IS_RANDO) { GetItem_Draw(play, GID_SKULL_TOKEN_2); } else { - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); + 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; 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 abb65c1914..bea2f608fc 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 @@ -99,8 +99,8 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { } if (IS_RANDO) { - GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id, - play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); + 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 { if (flag) { Gfx_SetupDL_25Xlu(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 b12d7b4b03..fb93702aba 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 @@ -230,7 +230,8 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { func_8002ED80(&this->actor, play, 0); if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); + 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); @@ -249,9 +250,9 @@ void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { if (IS_RANDO) { GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_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 = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + 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); 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 a9cd364464..c1a0d67ecc 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 @@ -215,7 +215,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;