diff --git a/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp b/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp new file mode 100644 index 00000000000..825ecbe1bfb --- /dev/null +++ b/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp @@ -0,0 +1,17 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "macros.h" +} + +static constexpr int32_t CVAR_NOLIKELIKEITEMSTEAL_DEFAULT = 0; +#define CVAR_NOLIKELIKEITEMSTEAL_NAME CVAR_CHEAT("NoLikeLikeItemSteal") +#define CVAR_NOLIKELIKEITEMSTEAL_VALUE CVarGetInteger(CVAR_NOLIKELIKEITEMSTEAL_NAME, CVAR_NOLIKELIKEITEMSTEAL_DEFAULT) + +void RegisterNoLikeLikeItemSteal() { + COND_VB_SHOULD(VB_LIKE_LIKE_STEAL_EQUIPMENT, CVAR_NOLIKELIKEITEMSTEAL_VALUE, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterNoLikeLikeItemSteal, { CVAR_NOLIKELIKEITEMSTEAL_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/DropThrowOnlyActors.cpp b/soh/soh/Enhancements/DropThrowOnlyActors.cpp new file mode 100644 index 00000000000..260f1f183d8 --- /dev/null +++ b/soh/soh/Enhancements/DropThrowOnlyActors.cpp @@ -0,0 +1,17 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +void OnAllowThrowOnlyDrop(void* actor) { + Actor* thisx = (Actor*)actor; + if (CVarGetInteger(CVAR_ENHANCEMENT("DropThrowOnlyObjects"), 0)) { + thisx->flags &= ~ACTOR_FLAG_THROW_ONLY; + } else { + thisx->flags |= ACTOR_FLAG_THROW_ONLY; + } +} + +void RegisterAllowThrowOnlyDrop() { + GameInteractor::Instance->RegisterGameHook(OnAllowThrowOnlyDrop); +} + +static RegisterShipInitFunc initFunc(RegisterAllowThrowOnlyDrop, { CVAR_ENHANCEMENT("DropThrowOnlyObjects") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index 155b1af713e..19f8142a8c7 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -4,6 +4,8 @@ #include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Notification/Notification.h" #include "soh/OTRGlobals.h" +#include "soh/SohGui/ImGuiUtils.h" +#include "soh/SaveManager.h" extern "C" { #include "variables.h" @@ -11,6 +13,8 @@ extern "C" { #include "macros.h" extern PlayState* gPlayState; GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID); +GetItemID RetrieveGetItemIDFromItemID(ItemID itemID); +RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID); } #define CVAR_EXTRA_TRAPS_NAME CVAR_ENHANCEMENT("ExtraTraps.Enabled") @@ -28,19 +32,49 @@ typedef enum { ADD_AMMO_TRAP, ADD_KILL_TRAP, ADD_TELEPORT_TRAP, + ADD_POCKET_TRAP, + ADD_PERMADEATH_TRAP, ADD_TRAP_MAX } AltTrapType; static AltTrapType roll = ADD_TRAP_MAX; static int statusTimer = -1; static int eventTimer = -1; +static int permaDeathTimer = -1; +bool shouldFileDelete = false; const char* altTrapTypeCvars[] = { - CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), - CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"), - CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"), - CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"), - CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), + CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), + CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"), + CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"), + CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"), + CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), + CVAR_ENHANCEMENT("ExtraTraps.Pocket"), CVAR_ENHANCEMENT("ExtraTraps.Permadeath"), +}; + +static std::unordered_map itemToQuestMap = { + { ITEM_MEDALLION_FOREST, QUEST_MEDALLION_FOREST }, + { ITEM_MEDALLION_FIRE, QUEST_MEDALLION_FIRE }, + { ITEM_MEDALLION_WATER, QUEST_MEDALLION_WATER }, + { ITEM_MEDALLION_SPIRIT, QUEST_MEDALLION_SPIRIT }, + { ITEM_MEDALLION_SHADOW, QUEST_MEDALLION_SHADOW }, + { ITEM_MEDALLION_LIGHT, QUEST_MEDALLION_LIGHT }, + { ITEM_SONG_MINUET, QUEST_SONG_MINUET }, + { ITEM_SONG_BOLERO, QUEST_SONG_BOLERO }, + { ITEM_SONG_SERENADE, QUEST_SONG_SERENADE }, + { ITEM_SONG_REQUIEM, QUEST_SONG_REQUIEM }, + { ITEM_SONG_NOCTURNE, QUEST_SONG_NOCTURNE }, + { ITEM_SONG_PRELUDE, QUEST_SONG_PRELUDE }, + { ITEM_SONG_LULLABY, QUEST_SONG_LULLABY }, + { ITEM_SONG_EPONA, QUEST_SONG_EPONA }, + { ITEM_SONG_SARIA, QUEST_SONG_SARIA }, + { ITEM_SONG_SUN, QUEST_SONG_SUN }, + { ITEM_SONG_TIME, QUEST_SONG_TIME }, + { ITEM_SONG_STORMS, QUEST_SONG_STORMS }, + { ITEM_KOKIRI_EMERALD, QUEST_KOKIRI_EMERALD }, + { ITEM_GORON_RUBY, QUEST_GORON_RUBY }, + { ITEM_ZORA_SAPPHIRE, QUEST_ZORA_SAPPHIRE }, + { ITEM_GERUDO_CARD, QUEST_GERUDO_CARD }, }; std::vector getEnabledAddTraps() { @@ -60,11 +94,149 @@ std::vector getEnabledAddTraps() { return enabledAddTraps; }; +void TriggerVoidOut() { + Player* player = GET_PLAYER(gPlayState); + + Audio_PlaySoundGeneral(NA_SE_EN_BUBLE_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + // Hyrule Castle: Very likely to fall through floor, so we force a specific entrance + if (gPlayState->sceneNum == SCENE_HYRULE_CASTLE || gPlayState->sceneNum == SCENE_OUTSIDE_GANONS_CASTLE) { + gPlayState->nextEntranceIndex = ENTR_CASTLE_GROUNDS_SOUTH_EXIT; + } else { + gSaveContext.respawnFlag = 1; + gPlayState->nextEntranceIndex = gSaveContext.entranceIndex; + + // Preserve the player's position and orientation + gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = gPlayState->nextEntranceIndex; + gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = gPlayState->roomCtx.curRoom.num; + gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = player->actor.world.pos; + gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = player->actor.shape.rot.y; + + if (gPlayState->roomCtx.curRoom.behaviorType2 < 4) { + gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF; + } else { + // Scenes with static backgrounds use a special camera we need to preserve + Camera* camera = GET_ACTIVE_CAM(gPlayState); + s16 camId = camera->camDataIdx; + gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0D00 | camId; + } + } + + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gPlayState->transitionType = TRANS_TYPE_INSTANT; + gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST; +} + +void ExecutePocketTrap() { + std::vector currentLoadout; + + for (auto& items : itemMapping) { + if (INV_CONTENT(items.second.id) == items.second.id) { + currentLoadout.push_back(items.second.id); + continue; + } + auto questItem = itemToQuestMap.find( + (ItemID)items.second.id); // std::find(itemToQuestMap.begin(), itemToQuestMap.end(), items.second.id); + if (questItem == itemToQuestMap.end()) { + continue; + } + if (CHECK_QUEST_ITEM(questItem->second)) { + currentLoadout.push_back(items.second.id); + continue; + } + } + + if (currentLoadout.size() == 0) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + + RandomizerGet rgItem = RG_NONE; + + uint32_t roll = Random(0, currentLoadout.size() - 1); + if (currentLoadout[roll] >= ITEM_SONG_MINUET) { + rgItem = RetrieveRandomizerGetFromItemID((ItemID)currentLoadout[roll]); + } else { + GetItemID getItemId = RetrieveGetItemIDFromItemID((ItemID)currentLoadout[roll]); + for (auto& randoGet : Rando::StaticData::GetItemTable()) { + if (randoGet.GetItemID() == getItemId) { + rgItem = randoGet.GetRandomizerGet(); + break; + } + } + } + + if (rgItem == RG_NONE) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + + for (auto& check : Rando::StaticData::GetLocationTable()) { + if (Rando::Context::GetInstance()->GetItemLocation(check.GetRandomizerCheck())->GetPlacedRandomizerGet() == + rgItem) { + if (check.GetRandomizerCheck() == RC_UNKNOWN_CHECK || check.GetRandomizerCheck() == RC_LINKS_POCKET) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + switch (check.GetActorID()) { + case ACTOR_EN_BOX: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_TREASURE, + check.GetActorParams() & 0x1F); + break; + default: + if (check.GetCollectionCheck().type != SPOILER_CHK_NONE) { + switch (check.GetCollectionCheck().type) { + case SPOILER_CHK_ITEM_GET_INF: + Flags_UnsetItemGetInf(check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_RANDOMIZER_INF: + Flags_UnsetRandomizerInf((RandomizerInf)check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_EVENT_CHK_INF: + Flags_UnsetEventInf(check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_CHEST: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_TREASURE, + check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_COLLECTABLE: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_COLLECTIBLE, + check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_INF_TABLE: + Flags_UnsetInfTable(check.GetCollectionCheck().flag); + break; + default: + GameInteractor::RawAction::FreezePlayer(); + return; + } + } + break; + } + + Rando::Context::GetInstance()->GetItemLocation(check.GetRandomizerCheck())->SetCheckStatus(RCSHOW_SEEN); + INV_CONTENT(currentLoadout[roll]) = ITEM_NONE; + break; + } + } + + Notification::Emit({ .itemIcon = (const char*)gItemIcons[currentLoadout[roll]], + .prefix = "You've lost your", + .prefixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + .message = Rando::StaticData::RetrieveItem(rgItem).GetName().english.c_str(), + .messageColor = UIWidgets::ColorValues.at(UIWidgets::Colors::Green), + .suffix = ". I remember seeing it somewhere...", + .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White) }); + + TriggerVoidOut(); +} + static void RollRandomTrap(uint32_t seed) { uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : static_cast(gSaveContext.ship.stats.fileCreatedAt)); Random_Init(finalSeed); - + // roll = ADD_PERMADEATH_TRAP; roll = RandomElement(getEnabledAddTraps()); switch (roll) { case ADD_ICE_TRAP: @@ -104,6 +276,18 @@ static void RollRandomTrap(uint32_t seed) { case ADD_TELEPORT_TRAP: eventTimer = 3; break; + case ADD_POCKET_TRAP: + ExecutePocketTrap(); + break; + case ADD_PERMADEATH_TRAP: + permaDeathTimer = 180; + shouldFileDelete = true; + Notification::Emit({ .itemIcon = (const char*)gItemIcons[ITEM_BOMB], + .message = "Collect a Check or Perma Death executes in ", + .messageColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + .suffix = "60 seconds.", + .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::Red) }); + break; default: break; } @@ -168,6 +352,17 @@ static void OnPlayerUpdate() { break; } } + if (permaDeathTimer == 0) { + if (shouldFileDelete) { + SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); + std::reinterpret_pointer_cast( + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) + ->Dispatch("reset"); + } + } + if (permaDeathTimer >= 0) { + permaDeathTimer--; + } if (statusTimer >= 0) { statusTimer--; } @@ -196,6 +391,20 @@ void RegisterExtraTraps() { GameInteractor::RawAction::FreezePlayer(); } }); + + COND_HOOK(OnFlagSet, CVAR_EXTRA_TRAPS_NAME, [](int16_t flagType, int16_t flag) { + SPDLOG_INFO("Flag Set Here {}", std::to_string(flagType).c_str()); + if (flagType != FLAG_SCENE_CLEAR) { + shouldFileDelete = false; + } + }); + + COND_HOOK(OnSceneFlagSet, CVAR_EXTRA_TRAPS_NAME, [](int16_t sceneNum, int16_t flagType, int16_t flag) { + SPDLOG_INFO("Scene Flag Set Here {}", std::to_string(flagType).c_str()); + if (flagType != FLAG_SCENE_CLEAR) { + shouldFileDelete = false; + } + }); } static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME }); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 463f900e0d4..ed5bae40e1a 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1685,6 +1685,30 @@ void ResetBaseOptions() { .Tooltip(""); } +void DrawRandomizerTab() { + auto ctx = OTRGlobals::Instance->gRandoContext; + ImGui::Text("Silver Rupee Counts"); + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES)) { + for (int32_t i = RG_SILVER_RUPEE_FIRST; i <= RG_SILVER_RUPEE_LAST; i++) { + RandomizerGet rgid = static_cast(i); + int32_t collected = ctx->GetSilverRupeeCounter(rgid).GetCollected(); + PushStyleSlider(THEME_COLOR); + if (UIWidgets::SliderInt(Rando::StaticData::RetrieveItem(rgid).GetName().GetEnglish().c_str(), &collected, + UIWidgets::IntSliderOptions() + .DefaultValue(0) + .Max(ctx->GetSilverRupeeCounter(rgid).GetTotal()) + .Min(0) + .ShowButtons(true))) { + ctx->GetSilverRupeeCounter(rgid).SetCollected(collected); + } + PopStyleSlider(); + } + } else { + ImGui::Text("Silver Rupees are not shuffled"); + } + UIWidgets::PaddedSeparator(); +} + void SaveEditorWindow::DrawElement() { PushStyleTabs(THEME_COLOR); ImGui::PushFont(OTRGlobals::Instance->fontMonoLarger); @@ -1727,6 +1751,12 @@ void SaveEditorWindow::DrawElement() { ImGui::EndTabItem(); } + ResetBaseOptions(); + if (ImGui::BeginTabItem("Randomizer")) { + DrawRandomizerTab(); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); } diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 08d663c7e30..62ce5c69b8f 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -244,6 +244,14 @@ typedef enum { // - `*EnPoField` VB_BOTTLE_BIG_POE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*ObjWood02` + VB_BUSH_DROP_ITEM, + // #### `result` // ```c // ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) || @@ -1378,6 +1386,14 @@ typedef enum { // - `*EnOkarinaTag` VB_OKARINA_TAG_COMPLETED, + // #### `result` + // ```c + // this->getItemId != GI_NONE + // ``` + // #### `args` + // - `None` + VB_OPEN_CHEST, + // #### `result` // ```c // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) @@ -2236,6 +2252,14 @@ typedef enum { // - `*Actor` VB_RECIEVE_FALL_DAMAGE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnRr` + VB_LIKE_LIKE_DROP_COLLECTIBLE, + // #### `result` // ```c // true @@ -2244,6 +2268,14 @@ typedef enum { // - `*EnRr` VB_LIKE_LIKE_GRAB_PLAYER, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnRr` + VB_LIKE_LIKE_STEAL_EQUIPMENT, + // #### `result` // ```c // entry != NULL @@ -2290,6 +2322,27 @@ typedef enum { // #### `result` // ```c + // true + // ``` + // #### `args` + // - `*EnGSwitch` + VB_SILVER_RUPEE_COLLECT, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnGSwitch` + VB_SILVER_RUPEE_COUNT_CHECK, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnGSwitch` + VB_SILVER_RUPEE_SETUP_DRAW, // CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0) // ``` // #### `args` diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index ca360543fa4..cbfd10dea50 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -446,7 +446,7 @@ void DrawGameplayStatsHeader() { // if tag is empty (not a release build) if (gGitCommitTag[0] == 0) { GameplayStatsRow("Git Branch:", (char*)gGitBranch); - GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash); + GameplayStatsRow("Version : 8.0 | Git Commit Hash:", (char*)gGitCommitHash); } else { GameplayStatsRow("Build Version:", (char*)gBuildVersion); } diff --git a/soh/soh/Enhancements/item-tables/ItemTableTypes.h b/soh/soh/Enhancements/item-tables/ItemTableTypes.h index df59d67704a..8a45e0af57d 100644 --- a/soh/soh/Enhancements/item-tables/ItemTableTypes.h +++ b/soh/soh/Enhancements/item-tables/ItemTableTypes.h @@ -27,6 +27,7 @@ typedef enum GetItemCategory { /* 0x03 */ ITEM_CATEGORY_SMALL_KEY, /* 0x04 */ ITEM_CATEGORY_SKULLTULA_TOKEN, /* 0x05 */ ITEM_CATEGORY_MAJOR, + /* 0x06 */ ITEM_CATEGORY_SILVER_RUPEE, } GetItemCategory; #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \ diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp index 2b95522633a..df14cb4f3ca 100644 --- a/soh/soh/Enhancements/kaleido.cpp +++ b/soh/soh/Enhancements/kaleido.cpp @@ -18,6 +18,7 @@ extern PlayState* gPlayState; #include "textures/icon_item_static/icon_item_static.h" #include #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" +#include "soh/Enhancements/randomizer/dungeon.h" #include @@ -75,7 +76,7 @@ void KaleidoEntryIcon::Draw(PlayState* play, std::vector* mEntryDl) { G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW)); // icon - if (!mAchieved) { + if (mGrayscale) { mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255)); mEntryDl->push_back(gsSPGrayscale(true)); } @@ -146,6 +147,18 @@ Kaleido::Kaleido() { FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul")); yOffset += 18; } + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Get() > RO_DUNGEON_ITEM_LOC_VANILLA) { + for (int i = RG_SILVER_RUPEE_FIRST; i <= RG_SILVER_RUPEE_LAST; i++) { + uint8_t dungeonId = ctx->GetSilverRupeeCounter(static_cast(i)).DungeonID(); + RandomizerCheckQuest dungeonQuest = ctx->GetDungeon(dungeonId)->IsMQ() ? RCQUEST_MQ : RCQUEST_VANILLA; + RandomizerCheckQuest rupeeQuest = ctx->GetSilverRupeeCounter(static_cast(i)).Quest(); + if (dungeonQuest == rupeeQuest) { + mEntries.push_back( + std::make_shared(static_cast(i), 0, yOffset)); + yOffset += 18; + } + } + } } extern "C" { @@ -260,6 +273,7 @@ KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int ico void KaleidoEntryIconFlag::Update(PlayState* play) { mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast(mFlag)); + mGrayscale = !mAchieved; } KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, @@ -267,14 +281,20 @@ KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconRes int16_t x, int16_t y, int* watch, int required, int total) : mWatch(watch), mRequired(required), mTotal(total), KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) { - mCount = *mWatch; + if (mWatch != nullptr) { + mCount = *mWatch; + } + mAchieved = mCount >= mRequired; + mGrayscale = mCount == 0; BuildText(); BuildVertices(); } void KaleidoEntryIconCountRequired::BuildText() { std::ostringstream totals; - totals << mCount; + if (mCount < mRequired) { + totals << mCount; + } if (mRequired != 0 && mCount < mRequired) { totals << '/' << mRequired; } @@ -284,6 +304,49 @@ void KaleidoEntryIconCountRequired::BuildText() { mText = totals.str(); } +KaleidoEntrySilverRupeeCounter::KaleidoEntrySilverRupeeCounter(RandomizerGet rgid, int16_t x, int16_t y) + : mRgid(rgid), KaleidoEntryIconCountRequired(gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, + Color_RGBA8{ 255, 255, 255, 255 }, x, y) { + mCount = OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(mRgid).GetCollected(); + mRequired = OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(mRgid).GetTotal(); + mAchieved = mCount >= mRequired; + mGrayscale = mCount == 0; + BuildText(); + BuildVertices(); +} + +void KaleidoEntrySilverRupeeCounter::BuildText() { + KaleidoEntryIconCountRequired::BuildText(); + CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(mRgid).GetName()); + // Abbreviate Dungeon Names + name.Replace("Spirit Temple", "SpT"); + name.Replace("Shadow Temple", "ShT"); + name.Replace("Bottom of the Well", "BotW"); + name.Replace("Gerudo Training Grounds", "GTG"); + name.Replace("Dodongo's Cavern", "DC"); + name.Replace("Ice Cavern", "IC"); + name.Replace("Ganon's Castle", "GC"); + // Remove MQ to make spoilers less prevalent + name.Replace("MQ", ""); + // Remove "Silver Rupee" from the name + name.Replace("Silver Rupee", ""); + if (!mText.empty()) { + mText += " "; + } + mText += name.GetForCurrentLanguage(); +} + +void KaleidoEntrySilverRupeeCounter::Update(PlayState* play) { + int newCount = OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(mRgid).GetCollected(); + if (mCount != newCount) { + mCount = newCount; + BuildText(); + RebuildVertices(); + mAchieved = mCount >= mRequired; + mGrayscale = mCount == 0; + } +} + void KaleidoEntryIcon::BuildVertices() { int offsetY = 0; int offsetX = 0; @@ -294,6 +357,19 @@ void KaleidoEntryIcon::BuildVertices() { offsetX += 18; for (size_t i = 0; i < mText.length(); i++) { int charWidth = static_cast(Ship_GetCharFontWidth(mText[i])); + if ((offsetX + charWidth) > 220) { + offsetX -= Ship_GetCharFontWidth(mText[i - 1]); + offsetX -= Ship_GetCharFontWidth(mText[i - 2]); + mText = mText.substr(0, i - 2) + "..."; + int periodWidth = Ship_GetCharFontWidth('.'); + Ship_CreateQuadVertexGroup(&(vertices)[(i - 1) * 4], offsetX, offsetY, periodWidth, 16, 0); + offsetX += periodWidth; + Ship_CreateQuadVertexGroup(&(vertices)[(i)*4], offsetX, offsetY, periodWidth, 16, 0); + offsetX += periodWidth; + Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, periodWidth, 16, 0); + offsetX += periodWidth; + break; + } Ship_CreateQuadVertexGroup(&(vertices)[(i + 1) * 4], offsetX, offsetY, charWidth, 16, 0); offsetX += charWidth; } @@ -326,6 +402,7 @@ void KaleidoEntryIconCountRequired::Update(PlayState* play) { BuildText(); RebuildVertices(); mAchieved = mCount >= mRequired; + mGrayscale = mCount == 0; } } @@ -381,11 +458,13 @@ void KaleidoEntryOcarinaButtons::Update(PlayState* play) { mButtonCollected[4] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_RIGHT) > 0; CalculateColors(); mAchieved = false; + mGrayscale = true; for (int i = 0; i < mButtonCollected.size(); i++) { if (!mButtonCollected[i]) { mButtonColors[i] = Color_RGBA8{ 109, 109, 109, 255 }; } else { mAchieved = true; + mGrayscale = false; } } } @@ -406,7 +485,7 @@ void KaleidoEntryOcarinaButtons::Draw(PlayState* play, std::vector* mEntryD G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW)); // icon - if (!mAchieved) { + if (mGrayscale) { mEntryDl->push_back(gsDPSetGrayscaleColor(109, 109, 109, 255)); mEntryDl->push_back(gsSPGrayscale(true)); } diff --git a/soh/soh/Enhancements/kaleido.h b/soh/soh/Enhancements/kaleido.h index 7776afb6631..d298dbeb108 100644 --- a/soh/soh/Enhancements/kaleido.h +++ b/soh/soh/Enhancements/kaleido.h @@ -39,6 +39,7 @@ class KaleidoEntry { Vtx* vtx; std::string mText; bool mAchieved = false; + bool mGrayscale = true; }; /** @@ -128,17 +129,28 @@ class KaleidoEntryIconCountRequired : public KaleidoEntryIcon { * @param total The amount of this collectible available in the seed. Set to 0 to not render. */ KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, - int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, + int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch = nullptr, int required = 0, int total = 0); void Update(PlayState* play) override; + void BuildText(); + + protected: + int mRequired; + int mCount; private: int* mWatch; - int mRequired; int mTotal; - int mCount; +}; +class KaleidoEntrySilverRupeeCounter : public KaleidoEntryIconCountRequired { + public: + KaleidoEntrySilverRupeeCounter(RandomizerGet rgid, int16_t x, int16_t y); + void Update(PlayState* play) override; void BuildText(); + + private: + RandomizerGet mRgid; }; class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon { diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 3204ace653c..9b0a7f5886f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -1065,6 +1065,13 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) { AddElementsToPool(dungeonItems, dungeonBossKey); } + // randomize Silver Rupees + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) { + auto dungeonSilverRupees = FilterAndEraseFromPool( + ItemPool, [dungeon](const RandomizerGet i) { return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(dungeonItems, dungeonSilverRupees); + } + // randomize boss key and small keys together for even distribution AssumedFill(dungeonItems, dungeonLocations); @@ -1130,6 +1137,16 @@ static void RandomizeDungeonItems() { FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); AddElementsToPool(overworldItems, ganonBossKey); } + + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) { + auto silverRupees = FilterAndEraseFromPool( + ItemPool, [dungeon](const RandomizerGet i) { return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(anyDungeonItems, silverRupees); + } else if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { + auto silverRupees = FilterAndEraseFromPool( + ItemPool, [dungeon](const RandomizerGet i) { return dungeon->ContainsSilverRupee(i); }); + AddElementsToPool(overworldItems, silverRupees); + } } if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp index aa375716f68..fb17f6e5b81 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp @@ -2225,6 +2225,28 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß ein #Herz in Ganons Schloß# #[[1]]# verstecke.", /*french*/ "Selon moi, un #coeur dans le Château de Ganon# cache #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE] = HintText(CustomMessage("They say that #spinning blades in Ice Cavern# protect #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE] = HintText(CustomMessage("They say that a #freezing slippery room# hides #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE] = HintText(CustomMessage("They say that the #Bottom of the well acid pit# protects #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE] = HintText(CustomMessage("They say that a #timed boulder maze# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE] = HintText(CustomMessage("They say that #a pillar rising out of lava in the desert# holds #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE] = HintText(CustomMessage("They say that a #whirlpool in the desert# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_GATE_SILVER_RUPEE] = HintText(CustomMessage("They say that a #gate in the Spirit Temple# protects #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_BEAMOS_SILVER_RUPEE] = HintText(CustomMessage("They say that #Beamos in the Spirit Temple# guard #[[1]]# from a #child#.", {QM_RED, QM_GREEN, QM_LBLUE})); + hintTextTable[RHT_SPIRIT_BOULDER_SILVER_RUPEE] = HintText(CustomMessage("They say that #boulders in the Spirit Temple# guard #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_LOBBY_SILVER_RUPEE] = HintText(CustomMessage("They say that #in the first room of the Spirit Temple#, #[[1]]# can be found.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE] = HintText(CustomMessage("They say that #visible spinning scythes in the Shadow Temple# guard #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE] = HintText(CustomMessage("They say that #outside the door to falling spikes in the Shadow Temple#, #[[1]]# can be found.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE] = HintText(CustomMessage("They say that #invisible spikes in the Shadow Temple# guard #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_FOREST_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of the forest# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_FIRE_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of fire# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_WATER_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of water# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of the spirit# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of the shadows# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_LIGHT_TRIAL_SILVER_RUPEE] = HintText(CustomMessage("They say that #a trial of light# guards #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DODONGOS_CAVERN_SILVER_RUPEE] = HintText(CustomMessage("They say that #around a collapsible staircase#, #[[1]]# can be found.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE] = HintText(CustomMessage("They say that #invisible scythes in the Shadow Temple# guard #[[1]]#.", {QM_RED, QM_GREEN})); + // clang-format on } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 0c40dfdb9c4..487c761584b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -2126,6 +2126,15 @@ void StaticData::HintTable_Init_Exclude_Overworld() { HintText(CustomMessage("They say that a #tree in Lon Lon Ranch# contains #[[1]]#.", /*german*/ "", /*french*/ "Selon moi, un #arbre au Ranch Lon Lon# cache #[[1]]#.", { QM_RED, QM_GREEN })); + + hintTextTable[RHT_BUSH_HYRULE_FIELD] = + HintText(CustomMessage("They say that a #bush in Hyrle Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #buisson dans la Plaine d'Hyrule# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_BUSH_ZORAS_FOUNTAIN] = + HintText(CustomMessage("They say that a #bush in Zora's Fountain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #buisson à la Fontaine Zora# cache #[[1]]#.", { QM_RED, QM_GREEN })); // clang-format on } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index c74c0ff23b9..7a29ee20488 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -1964,6 +1964,8 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a gold fragment", /*german*/"ein Goldfragment", /*french*/"un fragment d'or")}); // /*spanish*/un fragmento dorado + hintTextTable[RHT_BEAN_SOUL] = HintText(CustomMessage("a bean soul", TODO_TRANSLATE, TODO_TRANSLATE)); + hintTextTable[RHT_GOHMA_SOUL] = HintText(CustomMessage("the soul of Gohma", /*german*/"Gohmas Seele", /*french*/"l'Âme de Gohma"), { CustomMessage("something webbed", /*german*/"etwas Verwobenes", /*french*/"un truc entoilé") @@ -2099,6 +2101,7 @@ void StaticData::HintTable_Init_Item() { }, { CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") }); // /*spanish*/un desbloqueador maestro + hintTextTable[RHT_OPEN_CHEST] = HintText(CustomMessage("the ability to open chests", /*german*/"!!!", /*french*/"!!!")); //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini")); @@ -2117,6 +2120,16 @@ void StaticData::HintTable_Init_Item() { hintTextTable[RHT_WALLET_INF] = HintText(CustomMessage("an infinite Wallet", /*german*/"die unendliche Geldbörse", /*french*/"une Bourse sans fond")); + hintTextTable[RHT_DC_SILVER_RUPEE] = HintText(CustomMessage("a Dodongo's Cavern Silver Rupee")); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_SILVER_RUPEE] = HintText(CustomMessage("a Bottom of the Well Silver Rupee")); + hintTextTable[RHT_ICE_CAVERN_SILVER_RUPEE] = HintText(CustomMessage("an Ice Cavern Silver Rupee")); + hintTextTable[RHT_BOTTOM_OF_THE_WELL] = HintText(CustomMessage("a Bottom of the Well Silver Rupee")); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE] = HintText(CustomMessage("a Gerudo Training Ground Silver Rupee")); + hintTextTable[RHT_SPIRIT_TEMPLE_SILVER_RUPEE] = HintText(CustomMessage("a Spirit Temple Silver Rupee")); + hintTextTable[RHT_SHADOW_TEMPLE_SILVER_RUPEE] = HintText(CustomMessage("a Shadow Temple Silver Rupee")); + hintTextTable[RHT_GANONS_CASTLE_SILVER_RUPEE] = HintText(CustomMessage("a Ganon's Castle Silver Rupee")); + hintTextTable[RHT_BOTTOMLESS_SILVER_RUPEE_POUCH] = HintText(CustomMessage("a pouch full of Silver Rupees")); + hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"Epona", /*french*/"Epona"), // /*spanish*/a Epona { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index e8cab933f58..15ad8405f29 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -591,6 +591,10 @@ void GenerateItemPool() { AddItemToMainPool(RG_PROGRESSIVE_SCALE); } + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST)) { + AddItemToMainPool(RG_OPEN_CHEST); + } + if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { // 32 total beehive locations AddItemToPool(PendingJunkPool, RG_RED_RUPEE, 23); @@ -611,6 +615,10 @@ void GenerateItemPool() { PlaceItemsForType(RCTYPE_NLTREE, treesActive, false); } + // Shuffle Bushes + bool bushesActive = (bool)ctx->GetOption(RSK_SHUFFLE_BUSHES); + PlaceItemsForType(RCTYPE_BUSH, bushesActive, false); + // Shuffle Crates bool overworldCratesActive = ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_OVERWORLD) || ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_ALL); @@ -758,6 +766,19 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, false, true); } + if (ctx->GetOption(RSK_SHUFFLE_BEAN_SOULS)) { + AddItemToMainPool(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL); + AddItemToMainPool(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL); + AddItemToMainPool(RG_DESERT_COLOSSUS_BEAN_SOUL); + AddItemToMainPool(RG_GERUDO_VALLEY_BEAN_SOUL); + AddItemToMainPool(RG_GRAVEYARD_BEAN_SOUL); + AddItemToMainPool(RG_KOKIRI_FOREST_BEAN_SOUL); + AddItemToMainPool(RG_LAKE_HYLIA_BEAN_SOUL); + AddItemToMainPool(RG_LOST_WOODS_BRIDGE_BEAN_SOUL); + AddItemToMainPool(RG_LOST_WOODS_BEAN_SOUL); + AddItemToMainPool(RG_ZORAS_RIVER_BEAN_SOUL); + } + if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS)) { AddItemToMainPool(RG_GOHMA_SOUL); AddItemToMainPool(RG_KING_DODONGO_SOUL); @@ -1269,6 +1290,67 @@ void GenerateItemPool() { ctx->possibleIceTrapModels.push_back(RG_BIGGORON_SWORD); } + // Add Silver Rupees to the pool if the setting is not on Start With or Vanilla + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Get() > RO_DUNGEON_ITEM_LOC_VANILLA) { + std::vector silversToAdd; + if (ctx->GetDungeon(Rando::ICE_CAVERN)->IsVanilla()) { + silversToAdd.push_back(RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE); + silversToAdd.push_back(RG_ICE_CAVERN_SLIDING_SILVER_RUPEE); + } + if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla()) { + silversToAdd.push_back(RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE); + } + if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUND)->IsVanilla()) { + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE); + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE); + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE); + } else { + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE); + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE); + silversToAdd.push_back(RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE); + } + if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsVanilla()) { + silversToAdd.push_back(RG_SPIRIT_GATE_SILVER_RUPEE); + silversToAdd.push_back(RG_SPIRIT_BEAMOS_SILVER_RUPEE); + silversToAdd.push_back(RG_SPIRIT_BOULDER_SILVER_RUPEE); + } else { + silversToAdd.push_back(RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE); + } + if (ctx->GetDungeon(Rando::SHADOW_TEMPLE)->IsVanilla()) { + silversToAdd.push_back(RG_SHADOW_SCYTHE_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE); + } else { + silversToAdd.push_back(RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE); + } + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsVanilla()) { + silversToAdd.push_back(RG_FOREST_TRIAL_SILVER_RUPEE); + silversToAdd.push_back(RG_FIRE_TRIAL_SILVER_RUPEE); + silversToAdd.push_back(RG_SPIRIT_TRIAL_SILVER_RUPEE); + silversToAdd.push_back(RG_LIGHT_TRIAL_SILVER_RUPEE); + } else { + silversToAdd.push_back(RG_FIRE_TRIAL_MQ_SILVER_RUPEE); + silversToAdd.push_back(RG_WATER_TRIAL_MQ_SILVER_RUPEE); + silversToAdd.push_back(RG_SHADOW_TRIAL_MQ_SILVER_RUPEE); + } + for (auto rgid : silversToAdd) { + AddItemToMainPool(rgid, ctx->GetSilverRupeeCounter(rgid).GetTotal()); + } + } + + if (ctx->GetOption(RSK_BOTTOMLESS_SILVER_RUPEE_POUCH)) { + AddItemToMainPool(RG_BOTTOMLESS_SILVER_RUPEE_POUCH); + } + + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { + AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD); + } + } + // Replace ice traps with junk from the pending junk pool if necessary if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_OFF)) { ReplaceMaxItem(RG_ICE_TRAP, 0); diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp index dda37b18a15..69b85a3e8cd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp @@ -65,6 +65,13 @@ void GenerateStartingInventory() { AddItemToInventory(RG_GERUDO_MEMBERSHIP_CARD); } + if (ctx->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Is(RO_DUNGEON_ITEM_LOC_STARTWITH)) { + for (int i = RG_SILVER_RUPEE_FIRST; i <= RG_SILVER_RUPEE_LAST; i++) { + ctx->GetSilverRupeeCounter(static_cast(i)) + .IncrementCollected(ctx->GetSilverRupeeCounter(static_cast(i)).GetTotal()); + } + } + // Starting Inventory Menu // Values are associated so that the count of items matches the index of // the option selected. If None is selected, the value will be zero and diff --git a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp index 75717f8e91e..d4a58ee5508 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp @@ -180,8 +180,9 @@ void RegisterShuffleFairies() { // collected, the vanilla code will handle that part automatically. FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params); if (!ShuffleFairies_FairyExists(fairyIdentity)) { - if (SpawnFairy(gossipStone->actor.world.pos.x, gossipStone->actor.world.pos.y, - gossipStone->actor.world.pos.z, params, fairyType)) { + Player* player = GET_PLAYER(gPlayState); + if (SpawnFairy(player->actor.world.pos.x, (player->actor.world.pos.y + 20), player->actor.world.pos.z, + params, fairyType)) { Audio_PlayActorSound2(&gossipStone->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY); // Set vanilla check for fairy spawned so it doesn't spawn the vanilla fairy afterwards as well. gossipStone->unk_19D = 0; diff --git a/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.cpp b/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.cpp new file mode 100644 index 00000000000..17ee2bd42e8 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.cpp @@ -0,0 +1,1010 @@ +#include "ShuffleSilverRupees.h" +#include "static_data.h" +#include +#include "draw.h" +#include + +extern "C" { +#include "variables.h" +#include "overlays/actors/ovl_En_G_Switch/z_en_g_switch.h" +#include +extern PlayState* gPlayState; +} + +CustomMessage GetSilverRupeeItemMessage(uint16_t rgid) { + CustomMessage messageEntry; + if (rgid >= RG_SILVER_RUPEE_FIRST && rgid <= RG_SILVER_RUPEE_LAST) { + messageEntry = + CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, RG_SILVER_RUPEE_FIRST); + auto ctx = OTRGlobals::Instance->gRandoContext; + bool complete = ctx->GetSilverRupeeCounter(static_cast(rgid)).AllCollected(); + if (complete) { + messageEntry.Replace("[[count_text]]", "That's all of them"); + } else { + int srCount = ctx->GetSilverRupeeCounter(static_cast(rgid)).GetCollected() + 1; + messageEntry.Replace("[[count_text]]", CustomMessage("You have collected %g[[count]]%w of them so far")); + messageEntry.Replace("[[count]]", std::to_string(srCount)); + } + messageEntry.Replace( + "[[rupee_name]]", + CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName())); + // Remove the "MQ" text from the item name to avoid *some* MQ dungeon spoiling. + messageEntry.Replace(" MQ", CustomMessage("")); + messageEntry.AutoFormat(); + } + return messageEntry; +} + +extern "C" void EnGSwitch_RandomizerDraw(Actor* thisx, PlayState* play) { + EnGSwitch* srActor = reinterpret_cast(thisx); + Matrix_Push(); + Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY); + if (srActor->type == ENGSWITCH_SILVER_RUPEE) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + EnItem00_CustomItemsParticles(thisx, play, GET_ITEM_MYSTERY); + GetItemEntry_Draw(play, GET_ITEM_MYSTERY); + } else { + SilverRupeeIdentity* srIdentity = ObjectExtension::GetInstance().Get(srActor); + EnItem00_CustomItemsParticles(thisx, play, srIdentity->itemEntry); + GetItemEntry_Draw(play, srIdentity->itemEntry); + } + Matrix_Pop(); + } +} + +SilverRupeeIdentity IdentifySilverRupee(Vec3f_ pos) { + SilverRupeeIdentity srIdentity; + uint16_t sceneNum = gPlayState->sceneNum; + int16_t param1 = (int16_t)pos.x; + int16_t param2 = (int16_t)pos.z; + // Two particular silver rupees in Master Quest Shadow Temple have + // the same X and Z coordinates. We have to make an exception here + // and look them up by X and Y coordinates instead. + if (sceneNum == SCENE_SHADOW_TEMPLE && param1 == 2110 && param2 == 3372) { + param2 = (int16_t)pos.y; + } + Rando::Location* location = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor( + ACTOR_EN_G_SWITCH, sceneNum, TWO_ACTOR_PARAMS(param1, param2)); + if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) { + LUSLOG_WARN("SilverRupeeIdentity did not receive a valid RC value (%d).", location->GetRandomizerCheck()); + assert(false); + } else { + srIdentity.index.randomizerCheck = location->GetRandomizerCheck(); + srIdentity.itemEntry = + OTRGlobals::Instance->gRandoContext->GetFinalGIEntry(srIdentity.index.randomizerCheck, true, GI_NONE); + srIdentity.randomizerInf = static_cast(location->GetCollectionCheck().flag); + } + return srIdentity; +} + +std::unordered_map Rando::StaticData::silverTrackerMap = { + { { SCENE_ICE_CAVERN, RCQUEST_VANILLA, 328 }, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE }, + { { SCENE_ICE_CAVERN, RCQUEST_VANILLA, 329 }, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE }, + { { SCENE_BOTTOM_OF_THE_WELL, RCQUEST_VANILLA, 351 }, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE }, + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_VANILLA, 348 }, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE }, + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_VANILLA, 332 }, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE }, + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_VANILLA, 347 }, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE }, + { { SCENE_SPIRIT_TEMPLE, RCQUEST_VANILLA, 325 }, RG_SPIRIT_GATE_SILVER_RUPEE }, + { { SCENE_SPIRIT_TEMPLE, RCQUEST_VANILLA, 330 }, RG_SPIRIT_BEAMOS_SILVER_RUPEE }, + { { SCENE_SPIRIT_TEMPLE, RCQUEST_VANILLA, 322 }, RG_SPIRIT_BOULDER_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_VANILLA, 321 }, RG_SHADOW_SCYTHE_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_VANILLA, 329 }, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_VANILLA, 328 }, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_VANILLA, 334 }, RG_FOREST_TRIAL_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_VANILLA, 329 }, RG_FIRE_TRIAL_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_VANILLA, 331 }, RG_SPIRIT_TRIAL_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_VANILLA, 338 }, RG_LIGHT_TRIAL_SILVER_RUPEE }, + // MQ + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_MQ, 348 }, RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE }, + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_MQ, 396 }, RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE }, + { { SCENE_GERUDO_TRAINING_GROUND, RCQUEST_MQ, 219 }, RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE }, + { { SCENE_DODONGOS_CAVERN, RCQUEST_MQ, 357 }, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_MQ, 321 }, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_MQ, 643 }, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_MQ, 337 }, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE }, + { { SCENE_SHADOW_TEMPLE, RCQUEST_MQ, 648 }, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE }, + { { SCENE_SPIRIT_TEMPLE, RCQUEST_MQ, 375 }, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_MQ, 322 }, RG_WATER_TRIAL_MQ_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_MQ, 331 }, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE }, + { { SCENE_INSIDE_GANONS_CASTLE, RCQUEST_MQ, 321 }, RG_FIRE_TRIAL_MQ_SILVER_RUPEE }, +}; + +void EnGSwitch_RandomizerInit(void* actor) { + EnGSwitch* srActor = static_cast(actor); + SilverRupeeIdentity srIdentity; + if (srActor->type == ENGSWITCH_SILVER_RUPEE) { + srIdentity = IdentifySilverRupee(srActor->actor.world.pos); + if (Flags_GetRandomizerInf(srIdentity.randomizerInf)) { + Actor_Kill(&srActor->actor); + } + ObjectExtension::GetInstance().Set(actor, std::move(srIdentity)); + } else if (srActor->type == ENGSWITCH_SILVER_TRACKER) { + Rando::Identifier identifier = { static_cast(gPlayState->sceneNum), + ResourceMgr_IsSceneMasterQuest(gPlayState->sceneNum) ? RCQUEST_MQ + : RCQUEST_VANILLA, + srActor->actor.params }; + srIdentity.index.randomizerGet = Rando::StaticData::silverTrackerMap.at(identifier); + ObjectExtension::GetInstance().Set(actor, std::move(srIdentity)); + } else { + LUSLOG_INFO("EnGSwitch Actor Type %d, no Randomizer logic required", srActor->type); + } +} + +void RegisterShuffleSilverRupees() { + bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SILVER_RUPEES); + + COND_ID_HOOK(OnActorInit, ACTOR_EN_G_SWITCH, shouldRegister, EnGSwitch_RandomizerInit); + COND_VB_SHOULD(VB_SILVER_RUPEE_COLLECT, shouldRegister, { + EnGSwitch* srActor = va_arg(args, EnGSwitch*); + SilverRupeeIdentity* srIdentity = ObjectExtension::GetInstance().Get(srActor); + Flags_SetRandomizerInf(srIdentity->randomizerInf); + Actor_Kill(&srActor->actor); + *should = false; + }); + COND_VB_SHOULD(VB_SILVER_RUPEE_COUNT_CHECK, shouldRegister, { + EnGSwitch* srActor = va_arg(args, EnGSwitch*); + SilverRupeeIdentity* srIdentity = ObjectExtension::GetInstance().Get(srActor); + // check if all silver rupees for that room have been collected + // we run this every frame in case one of the rupees for a room + // is randomized into the same room. Without this we'd need to + // reload the scene after collecting it to unlock the door. + if (OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(srIdentity->index.randomizerGet) + .AllCollected()) { + if ((gPlayState->sceneNum == SCENE_GERUDO_TRAINING_GROUND) && (srActor->actor.room == 2)) { + Flags_SetTempClear(gPlayState, srActor->actor.room); + } else { + Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); + Flags_SetSwitch(gPlayState, srActor->switchFlag); + } + Actor_Kill(&srActor->actor); + } + *should = false; + }); + COND_VB_SHOULD(VB_SILVER_RUPEE_SETUP_DRAW, shouldRegister, { + EnGSwitch* srActor = va_arg(args, EnGSwitch*); + srActor->actor.draw = (ActorFunc)EnGSwitch_RandomizerDraw; + *should = false; + }) +} + +static RegisterShipInitFunc initFunc(RegisterShuffleSilverRupees, { "IS_RANDO" }); + +void Rando::StaticData::RegisterSilverRupeeLocations() { + locationTable[RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1] = Location::Base( + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(389, -382), "Spinning Blades Silver Rupee 1", + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1)); + locationTable[RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2] = Location::Base( + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(414, -579), "Spinning Blades Silver Rupee 2", + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2)); + locationTable[RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3] = Location::Base( + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(278, -637), "Spinning Blades Silver Rupee 3", + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3)); + locationTable[RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4] = Location::Base( + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(198, -388), "Spinning Blades Silver Rupee 4", + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4)); + locationTable[RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5] = Location::Base( + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(1, -143), "Spinning Blades Silver Rupee 5", + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5)); + + locationTable[RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_1] = Location::Base( + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1040, -485), "Sliding Puzzle Silver Rupee 1", + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_1)); + locationTable[RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_2] = Location::Base( + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1120, -1577), "Sliding Puzzle Silver Rupee 2", + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_2)); + locationTable[RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_3] = Location::Base( + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1294, -899), "Sliding Puzzle Silver Rupee 3", + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_3)); + locationTable[RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_4] = Location::Base( + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1558, -951), "Sliding Puzzle Silver Rupee 4", + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_4)); + locationTable[RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_5] = Location::Base( + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_ICE_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1676, -552), "Sliding Puzzle Silver Rupee 5", + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_5)); + + locationTable[RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1] = Location::Base( + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_BOTTOM_OF_THE_WELL, + ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-259, -234), "Basement Silver Rupee 1", + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1)); + locationTable[RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2] = Location::Base( + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_BOTTOM_OF_THE_WELL, + ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-402, -401), "Basement Silver Rupee 2", + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2)); + locationTable[RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3] = Location::Base( + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_BOTTOM_OF_THE_WELL, + ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-560, -291), "Basement Silver Rupee 3", + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3)); + locationTable[RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4] = Location::Base( + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_BOTTOM_OF_THE_WELL, + ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-614, -297), "Basement Silver Rupee 4", + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4)); + locationTable[RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5] = Location::Base( + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_BOTTOM_OF_THE_WELL, + ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-796, -150), "Basement Silver Rupee 5", + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1887, -2134), "Boulder Maze Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1627, -1462), "Boulder Maze Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1579, -999), "Boulder Maze Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1886, -956), "Boulder Maze Silver Rupee 4", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1332, -992), "Boulder Maze Silver Rupee 5", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1560, -1861), "Lava Room Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1437, -2193), "Lava Room Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1134, -1841), "Lava Room Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1558, -1370), "Lava Room Silver Rupee 4", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1320, -1248), "Lava Room Silver Rupee 5", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2160, -1315), "Whirlpool Room Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2078, -1458), "Whirlpool Room Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2453, -1612), "Whirlpool Room Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2497, -1465), "Whirlpool Room Silver Rupee 4", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2308, -1464), "Whirlpool Room Silver Rupee 5", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5)); + + locationTable[RC_SPIRIT_GATE_SILVER_RUPEE_1] = Location::Base( + RC_SPIRIT_GATE_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-335, -1409), "Child Gate Silver Rupee 1", RHT_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_1)); + locationTable[RC_SPIRIT_GATE_SILVER_RUPEE_2] = Location::Base( + RC_SPIRIT_GATE_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-347, -1075), "Child Gate Silver Rupee 2", RHT_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_2)); + locationTable[RC_SPIRIT_GATE_SILVER_RUPEE_3] = Location::Base( + RC_SPIRIT_GATE_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-511, -1075), "Child Gate Silver Rupee 3", RHT_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_3)); + locationTable[RC_SPIRIT_GATE_SILVER_RUPEE_4] = Location::Base( + RC_SPIRIT_GATE_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-672, -1075), "Child Gate Silver Rupee 4", RHT_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_4)); + locationTable[RC_SPIRIT_GATE_SILVER_RUPEE_5] = Location::Base( + RC_SPIRIT_GATE_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-766, -1075), "Child Gate Silver Rupee 5", RHT_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_5)); + + locationTable[RC_SPIRIT_BEAMOS_SILVER_RUPEE_1] = Location::Base( + RC_SPIRIT_BEAMOS_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-984, -450), "Beamos Room Silver Rupee 1", RHT_SPIRIT_BEAMOS_SILVER_RUPEE, + RG_SPIRIT_BEAMOS_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_1)); + locationTable[RC_SPIRIT_BEAMOS_SILVER_RUPEE_2] = Location::Base( + RC_SPIRIT_BEAMOS_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1123, 428), "Beamos Room Silver Rupee 2", RHT_SPIRIT_BEAMOS_SILVER_RUPEE, + RG_SPIRIT_BEAMOS_SILVER_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_2)); + locationTable[RC_SPIRIT_BEAMOS_SILVER_RUPEE_3] = + Location::Base(RC_SPIRIT_BEAMOS_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1275, -247), + "Beamos Room Silver Rupee 3", RHT_SPIRIT_BEAMOS_SILVER_RUPEE, RG_SPIRIT_BEAMOS_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_3)); + locationTable[RC_SPIRIT_BEAMOS_SILVER_RUPEE_4] = + Location::Base(RC_SPIRIT_BEAMOS_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1433, -283), + "Beamos Room Silver Rupee 4", RHT_SPIRIT_BEAMOS_SILVER_RUPEE, RG_SPIRIT_BEAMOS_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_4)); + locationTable[RC_SPIRIT_BEAMOS_SILVER_RUPEE_5] = + Location::Base(RC_SPIRIT_BEAMOS_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1836, -446), + "Beamos Room Silver Rupee 5", RHT_SPIRIT_BEAMOS_SILVER_RUPEE, RG_SPIRIT_BEAMOS_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_5)); + + locationTable[RC_SPIRIT_BOULDER_SILVER_RUPEE_1] = + Location::Base(RC_SPIRIT_BOULDER_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1573, -920), + "Boulder Room Silver Rupee 1", RHT_SPIRIT_BOULDER_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_1)); + locationTable[RC_SPIRIT_BOULDER_SILVER_RUPEE_2] = + Location::Base(RC_SPIRIT_BOULDER_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1856, -1219), + "Boulder Room Silver Rupee 2", RHT_SPIRIT_BOULDER_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_2)); + locationTable[RC_SPIRIT_BOULDER_SILVER_RUPEE_3] = + Location::Base(RC_SPIRIT_BOULDER_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1856, -944), + "Boulder Room Silver Rupee 3", RHT_SPIRIT_BOULDER_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_3)); + locationTable[RC_SPIRIT_BOULDER_SILVER_RUPEE_4] = + Location::Base(RC_SPIRIT_BOULDER_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1284, -813), + "Boulder Room Silver Rupee 4", RHT_SPIRIT_BOULDER_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_4)); + locationTable[RC_SPIRIT_BOULDER_SILVER_RUPEE_5] = + Location::Base(RC_SPIRIT_BOULDER_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1284, -1355), + "Boulder Room Silver Rupee 5", RHT_SPIRIT_BOULDER_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_SCYTHE_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_SCYTHE_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3399, -838), "Spinning Scythe Silver Rupee 1", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_SCYTHE_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_SCYTHE_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2869, -948), "Spinning Scythe Silver Rupee 2", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_SCYTHE_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_SCYTHE_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3554, -1432), "Spinning Scythe Silver Rupee 3", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_SCYTHE_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_SCYTHE_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3007, -1222), "Spinning Scythe Silver Rupee 4", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_SCYTHE_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_SCYTHE_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3243, -1061), "Spinning Scythe Silver Rupee 5", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(1998, 3358), "Outside Spike Rain Room Silver Rupee 1", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2243, 3361), "Outside Spike Rain Room Silver Rupee 2", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, 3368), "Outside Spike Rain Room Silver Rupee 3", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2115, 3738), "Outside Spike Rain Room Silver Rupee 4", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2131, 3030), "Outside Spike Rain Room Silver Rupee 5", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2254, 988), "Invisible Spikes Room Silver Rupee 1", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2135, 1297), "Invisible Spikes Room Silver Rupee 2", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1208), "Invisible Spikes Room Silver Rupee 3", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2940, 1069), "Invisible Spikes Room Silver Rupee 4", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2042, 849), "Invisible Spikes Room Silver Rupee 5", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5)); + + locationTable[RC_FOREST_TRIAL_SILVER_RUPEE_1] = + Location::Base(RC_FOREST_TRIAL_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1634, 1550), + "Forest Trial Silver Rupee 1", RHT_FOREST_TRIAL_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_1)); + locationTable[RC_FOREST_TRIAL_SILVER_RUPEE_2] = + Location::Base(RC_FOREST_TRIAL_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1651, 2021), + "Forest Trial Silver Rupee 2", RHT_FOREST_TRIAL_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_2)); + locationTable[RC_FOREST_TRIAL_SILVER_RUPEE_3] = + Location::Base(RC_FOREST_TRIAL_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1538, 2225), + "Forest Trial Silver Rupee 3", RHT_FOREST_TRIAL_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_3)); + locationTable[RC_FOREST_TRIAL_SILVER_RUPEE_4] = + Location::Base(RC_FOREST_TRIAL_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1361, 1222), + "Forest Trial Silver Rupee 4", RHT_FOREST_TRIAL_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_4)); + locationTable[RC_FOREST_TRIAL_SILVER_RUPEE_5] = + Location::Base(RC_FOREST_TRIAL_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1247, 1787), + "Forest Trial Silver Rupee 5", RHT_FOREST_TRIAL_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_5)); + + locationTable[RC_FIRE_TRIAL_SILVER_RUPEE_1] = + Location::Base(RC_FIRE_TRIAL_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1867, -2754), + "Fire Trial Silver Rupee 1", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_1)); + locationTable[RC_FIRE_TRIAL_SILVER_RUPEE_2] = + Location::Base(RC_FIRE_TRIAL_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-604, -2592), + "Fire Trial Silver Rupee 2", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_2)); + locationTable[RC_FIRE_TRIAL_SILVER_RUPEE_3] = + Location::Base(RC_FIRE_TRIAL_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-515, -3253), + "Fire Trial Silver Rupee 3", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_3)); + locationTable[RC_FIRE_TRIAL_SILVER_RUPEE_4] = + Location::Base(RC_FIRE_TRIAL_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1555, -2317), + "Fire Trial Silver Rupee 4", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_4)); + locationTable[RC_FIRE_TRIAL_SILVER_RUPEE_5] = + Location::Base(RC_FIRE_TRIAL_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-854, -3679), + "Fire Trial Silver Rupee 5", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_5)); + + locationTable[RC_SPIRIT_TRIAL_SILVER_RUPEE_1] = + Location::Base(RC_SPIRIT_TRIAL_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1142, 639), + "Spirit Trial Silver Rupee 1", RHT_SPIRIT_TRIAL_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_1)); + locationTable[RC_SPIRIT_TRIAL_SILVER_RUPEE_2] = + Location::Base(RC_SPIRIT_TRIAL_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-725, 942), + "Spirit Trial Silver Rupee 2", RHT_SPIRIT_TRIAL_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_2)); + locationTable[RC_SPIRIT_TRIAL_SILVER_RUPEE_3] = + Location::Base(RC_SPIRIT_TRIAL_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-865, 656), + "Spirit Trial Silver Rupee 3", RHT_SPIRIT_TRIAL_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_3)); + locationTable[RC_SPIRIT_TRIAL_SILVER_RUPEE_4] = + Location::Base(RC_SPIRIT_TRIAL_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-940, 270), + "Spirit Trial Silver Rupee 4", RHT_SPIRIT_TRIAL_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_4)); + locationTable[RC_SPIRIT_TRIAL_SILVER_RUPEE_5] = + Location::Base(RC_SPIRIT_TRIAL_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-829, 591), + "Spirit Trial Silver Rupee 5", RHT_SPIRIT_TRIAL_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_5)); + + locationTable[RC_LIGHT_TRIAL_SILVER_RUPEE_1] = + Location::Base(RC_LIGHT_TRIAL_SILVER_RUPEE_1, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2674, -777), + "Light Trial Silver Rupee 1", RHT_LIGHT_TRIAL_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_1)); + locationTable[RC_LIGHT_TRIAL_SILVER_RUPEE_2] = + Location::Base(RC_LIGHT_TRIAL_SILVER_RUPEE_2, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2680, -893), + "Light Trial Silver Rupee 2", RHT_LIGHT_TRIAL_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_2)); + locationTable[RC_LIGHT_TRIAL_SILVER_RUPEE_3] = + Location::Base(RC_LIGHT_TRIAL_SILVER_RUPEE_3, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2646, -839), + "Light Trial Silver Rupee 3", RHT_LIGHT_TRIAL_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_3)); + locationTable[RC_LIGHT_TRIAL_SILVER_RUPEE_4] = + Location::Base(RC_LIGHT_TRIAL_SILVER_RUPEE_4, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2649, -545), + "Light Trial Silver Rupee 4", RHT_LIGHT_TRIAL_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_4)); + locationTable[RC_LIGHT_TRIAL_SILVER_RUPEE_5] = + Location::Base(RC_LIGHT_TRIAL_SILVER_RUPEE_5, RCQUEST_VANILLA, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2509, -1091), + "Light Trial Silver Rupee 5", RHT_LIGHT_TRIAL_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_5)); + + locationTable[RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1] = + Location::Base(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_DODONGOS_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-1512, -1083), "Silver Rupee 1", + RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1)); + locationTable[RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2] = + Location::Base(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_DODONGOS_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-1907, -1243), "Silver Rupee 2", + RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2)); + locationTable[RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3] = + Location::Base(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_DODONGOS_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2411, -1836), "Silver Rupee 3", + RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3)); + locationTable[RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4] = + Location::Base(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_DODONGOS_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2189, -1834), "Silver Rupee 4", + RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4)); + locationTable[RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5] = + Location::Base(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_DODONGOS_CAVERN, + ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2277, -1362), "Silver Rupee 5", + RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3558, -1490), "Spinning Scythe Silver Rupee 1", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3399, -838), "Spinning Scythe Silver Rupee 2", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3243, -1061), "Spinning Scythe Silver Rupee 3", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3007, -1222), "Spinning Scythe Silver Rupee 4", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, ACTOR_EN_G_SWITCH, + SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2810, -961), "Spinning Scythe Silver Rupee 5", + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5667, 2686), "Invisible Scythe Silver Rupee 1", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5637, 2134), "Invisible Scythe Silver Rupee 2", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5601, 1898), "Invisible Scythe Silver Rupee 3", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5489, 2476), "Invisible Scythe Silver Rupee 4", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5466, 2243), "Invisible Scythe Silver Rupee 5", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5404, 1977), "Invisible Scythe Silver Rupee 6", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5270, 2453), "Invisible Scythe Silver Rupee 7", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5217, 1852), "Invisible Scythe Silver Rupee 8", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5158, 2315), "Invisible Scythe Silver Rupee 9", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5089, 2049), "Invisible Scythe Silver Rupee 10", + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10)); + + locationTable[RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2250, 3372), "Outside Spike Rain Silver Rupee 1", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2131, 3030), "Outside Spike Rain Silver Rupee 2", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2)); + // The following two locations have the same X and Z coordinates, so use X and Y for the params instead. + locationTable[RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, -970), "Outside Spike Rain Silver Rupee 3", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, -1092), "Outside Spike Rain Silver Rupee 4", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4)); + // Back to X and Z coordinates for the params. + locationTable[RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(1970, 3372), "Outside Spike Rain Silver Rupee 5", + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2940, 1069), "Invisible Spikes Silver Rupee 1", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2730, 876), "Invisible Spikes Silver Rupee 2", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2705, 1089), "Invisible Spikes Silver Rupee 3", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1404), "Invisible Spikes Silver Rupee 4", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1200), "Invisible Spikes Silver Rupee 5", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1208), "Invisible Spikes Silver Rupee 6", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 893), "Invisible Spikes Silver Rupee 7", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2254, 988), "Invisible Spikes Silver Rupee 8", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2135, 1297), "Invisible Spikes Silver Rupee 9", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9)); + locationTable[RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10] = Location::Base( + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SHADOW_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2042, 849), "Invisible Spikes Silver Rupee 10", + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10)); + + locationTable[RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1] = + Location::Base(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(744, 4), "Lobby Silver Rupee 1", + RHT_SPIRIT_LOBBY_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1)); + locationTable[RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2] = + Location::Base(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(967, -574), "Lobby Silver Rupee 2", + RHT_SPIRIT_LOBBY_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2)); + locationTable[RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3] = + Location::Base(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-160, 270), "Lobby Silver Rupee 3", + RHT_SPIRIT_LOBBY_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3)); + locationTable[RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4] = + Location::Base(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(160, 268), "Lobby Silver Rupee 4", + RHT_SPIRIT_LOBBY_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4)); + locationTable[RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5] = + Location::Base(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_SPIRIT_TEMPLE, + ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1016, -73), "Lobby Silver Rupee 5", + RHT_SPIRIT_LOBBY_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1261, -923), "Boulder Maze Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1886, -956), "Boulder Maze Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1480, -1000), "Boulder Maze Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_4] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1542, -1476), "Boulder Maze Silver Rupee 4", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_5] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(-1245, -2112), "Boulder Maze Silver Rupee 5", + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1317, -1243), "Lava Room Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1083, -1374), "Lava Room Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1560, -1380), "Lava Room Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_4] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1404, -1653), "Lava Room Silver Rupee 4", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_5] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1134, -1841), "Lava Room Silver Rupee 5", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_6] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_6, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(1560, -1861), "Lava Room Silver Rupee 6", + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_6)); + + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_1] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2160, -1315), "Toilet Room Silver Rupee 1", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_2] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2302, -1464), "Toilet Room Silver Rupee 2", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2)); + locationTable[RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_3] = + Location::Base(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, + RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, + TWO_ACTOR_PARAMS(2453, -1612), "Toilet Room Silver Rupee 3", + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3)); + + locationTable[RC_FIRE_TRIAL_MQ_SILVER_RUPEE_1] = + Location::Base(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1655, -2133), + "Fire Trial MQ Silver Rupee 1", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_1)); + locationTable[RC_FIRE_TRIAL_MQ_SILVER_RUPEE_2] = + Location::Base(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-686, -2945), + "Fire Trial MQ Silver Rupee 2", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_2)); + locationTable[RC_FIRE_TRIAL_MQ_SILVER_RUPEE_3] = + Location::Base(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2044, -2254), + "Fire Trial MQ Silver Rupee 3", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_3)); + locationTable[RC_FIRE_TRIAL_MQ_SILVER_RUPEE_4] = + Location::Base(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1891, -2753), + "Fire Trial MQ Silver Rupee 4", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_4)); + locationTable[RC_FIRE_TRIAL_MQ_SILVER_RUPEE_5] = + Location::Base(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-970, -3747), + "Fire Trial MQ Silver Rupee 5", RHT_FIRE_TRIAL_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_5)); + + locationTable[RC_WATER_TRIAL_MQ_SILVER_RUPEE_1] = + Location::Base(RC_WATER_TRIAL_MQ_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2905, -1263), + "Water Trial MQ Silver Rupee 1", RHT_WATER_TRIAL_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_1)); + locationTable[RC_WATER_TRIAL_MQ_SILVER_RUPEE_2] = + Location::Base(RC_WATER_TRIAL_MQ_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(3253, -649), + "Water Trial MQ Silver Rupee 2", RHT_WATER_TRIAL_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_2)); + locationTable[RC_WATER_TRIAL_MQ_SILVER_RUPEE_3] = + Location::Base(RC_WATER_TRIAL_MQ_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2905, -1478), + "Water Trial MQ Silver Rupee 3", RHT_WATER_TRIAL_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_3)); + locationTable[RC_WATER_TRIAL_MQ_SILVER_RUPEE_4] = + Location::Base(RC_WATER_TRIAL_MQ_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2912, -971), + "Water Trial MQ Silver Rupee 4", RHT_WATER_TRIAL_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_4)); + locationTable[RC_WATER_TRIAL_MQ_SILVER_RUPEE_5] = + Location::Base(RC_WATER_TRIAL_MQ_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2757, -765), + "Water Trial MQ Silver Rupee 5", RHT_WATER_TRIAL_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_5)); + + locationTable[RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_1] = + Location::Base(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_1, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1100, -2554), + "Shadow Trial MQ Silver Rupee 1", RHT_SHADOW_TRIAL_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_1)); + locationTable[RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_2] = + Location::Base(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_2, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1829, -4071), + "Shadow Trial MQ Silver Rupee 2", RHT_SHADOW_TRIAL_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_2)); + locationTable[RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_3] = + Location::Base(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_3, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1529, -4117), + "Shadow Trial MQ Silver Rupee 3", RHT_SHADOW_TRIAL_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_3)); + locationTable[RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_4] = + Location::Base(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_4, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1279, -3111), + "Shadow Trial MQ Silver Rupee 4", RHT_SHADOW_TRIAL_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_4)); + locationTable[RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_5] = + Location::Base(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_5, RCQUEST_MQ, RCTYPE_SILVER_RUPEE, RCAREA_GANONS_CASTLE, + ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1322, -2262), + "Shadow Trial MQ Silver Rupee 5", RHT_SHADOW_TRIAL_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_5)); +} + +static ObjectExtension::Register RegisterSilverRupeeIdentity; +static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterSilverRupeeLocations); + +Rando::SilverRupeeCounter::SilverRupeeCounter() : mCollected(0), mTotal(0), mRandoGet(RG_NONE) { +} + +Rando::SilverRupeeCounter::SilverRupeeCounter(uint8_t total, RandomizerGet randoGet, uint8_t dungeonId, + RandomizerCheckQuest quest) + : mCollected(0), mTotal(total), mRandoGet(randoGet), mDungeonId(dungeonId), mQuest(quest) { +} + +uint8_t Rando::SilverRupeeCounter::GetCollected() const { + return mCollected; +} + +uint8_t Rando::SilverRupeeCounter::GetTotal() const { + return mTotal; +} + +void Rando::SilverRupeeCounter::IncrementCollected(uint8_t amount) { + mCollected += amount; +} + +bool Rando::SilverRupeeCounter::AllCollected() { + return GetCollected() == GetTotal(); +} + +void Rando::SilverRupeeCounter::SetCollected(uint8_t newCollected) { + if (newCollected >= 0 && newCollected <= GetTotal()) { + mCollected = newCollected; + } +} + +uint8_t Rando::SilverRupeeCounter::DungeonID() { + return mDungeonId; +} + +RandomizerCheckQuest Rando::SilverRupeeCounter::Quest() { + return mQuest; +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.h b/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.h new file mode 100644 index 00000000000..4ea76aa3a9c --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleSilverRupees.h @@ -0,0 +1,43 @@ +#ifndef SHUFFLESILVERRUPEES_H +#define SHUFFLESILVERRUPEES_H + +#include "soh/Enhancements/item-tables/ItemTableTypes.h" +#include "randomizerTypes.h" + +typedef struct SilverRupeeIdentity { + RandomizerInf randomizerInf; + union { + RandomizerCheck randomizerCheck; + RandomizerGet randomizerGet; + } index; + GetItemEntry itemEntry; +} SilverRupeeIdentity; + +#ifdef __cplusplus +#include +CustomMessage GetSilverRupeeItemMessage(uint16_t rgid); +namespace Rando { +class SilverRupeeCounter { + public: + SilverRupeeCounter(); + SilverRupeeCounter(uint8_t total, RandomizerGet randoGet, uint8_t dungeonId, RandomizerCheckQuest quest); + + uint8_t GetCollected() const; + uint8_t GetTotal() const; + void IncrementCollected(uint8_t amount = 1); + bool AllCollected(); + void SetCollected(uint8_t newCollected); + uint8_t DungeonID(); + RandomizerCheckQuest Quest(); + + private: + uint8_t mCollected = 0; + uint8_t mTotal; + RandomizerGet mRandoGet; + uint8_t mDungeonId; + RandomizerCheckQuest mQuest; +}; +} // namespace Rando +#endif + +#endif // SHUFLESILVERRUPEES_H \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp index 14cb9c7b1d2..cf301c8c26c 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp @@ -36,50 +36,45 @@ static Gfx* D_80B3BF70[] = { extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); uint8_t EnWood02_RandomizerHoldsItem(EnWood02* treeActor, PlayState* play) { - const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { - return false; - } - // Don't pull randomized item if tree isn't randomized or is already checked - return IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get() && - !Flags_GetRandomizerInf(treeIdentity->randomizerInf) && treeIdentity->randomizerCheck != RC_UNKNOWN_CHECK; + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + return treeIdentity != nullptr && treeIdentity->randomizerCheck != RC_UNKNOWN_CHECK && + treeIdentity->randomizerInf != RAND_INF_MAX && !Flags_GetRandomizerInf(treeIdentity->randomizerInf); } extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { GetItemCategory getItemCategory; - GetItemEntry smallCrateItem; + GetItemEntry treeItem; auto treeActor = (EnWood02*)thisx; - int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); - int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); - - int isVanilla = - csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { return; } - if (isVanilla || treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { + int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); + int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); + int isVanilla = + csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); + + if (isVanilla) { getItemCategory = ITEM_CATEGORY_JUNK; } else { - smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); - getItemCategory = smallCrateItem.getItemCategory; + treeItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + getItemCategory = treeItem.getItemCategory; // If they have bombchus, don't consider the bombchu item major if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && - ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) || - (smallCrateItem.modIndex == MOD_NONE && - (smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 || - smallCrateItem.getItemId == GI_BOMBCHUS_20)))) { + ((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) || + (treeItem.modIndex == MOD_NONE && + (treeItem.getItemId == GI_BOMBCHUS_5 || treeItem.getItemId == GI_BOMBCHUS_10 || + treeItem.getItemId == GI_BOMBCHUS_20)))) { getItemCategory = ITEM_CATEGORY_JUNK; // If it's a bottle and they already have one, consider the item lesser - } else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && - smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && - smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) || - (smallCrateItem.modIndex == MOD_NONE && - (smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) { + } else if ((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && + treeItem.getItemId <= RG_BOTTLE_WITH_POE) || + (treeItem.modIndex == MOD_NONE && + (treeItem.getItemId == GI_BOTTLE || treeItem.getItemId == GI_MILK_BOTTLE))) { if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) { getItemCategory = ITEM_CATEGORY_LESSER; } @@ -110,7 +105,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { break; case ITEM_CATEGORY_LESSER: Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); - switch (smallCrateItem.itemId) { + switch (treeItem.itemId) { case ITEM_HEART_PIECE: case ITEM_HEART_PIECE_2: case ITEM_HEART_CONTAINER: @@ -133,7 +128,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) { const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { return; } @@ -152,26 +147,33 @@ void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) { void EnWood02_RandomizerInit(void* actorRef) { EnWood02* treeActor = static_cast(actorRef); - if (treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT) { + if ((treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT && + Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get()) || + (treeActor->actor.params > WOOD_TREE_KAKARIKO_ADULT && + treeActor->actor.params <= WOOD_BUSH_BLACK_LARGE_SPAWNED && + Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BUSHES).Get())) { auto treeIdentity = OTRGlobals::Instance->gRandomizer->IdentifyTree( gPlayState->sceneNum, (s16)treeActor->actor.world.pos.x, (s16)treeActor->actor.world.pos.z); - ObjectExtension::GetInstance().Set(actorRef, std::move(treeIdentity)); + if (treeIdentity.randomizerInf != RAND_INF_MAX && treeIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { + ObjectExtension::GetInstance().Set(actorRef, std::move(treeIdentity)); + } } } void RegisterShuffleTrees() { - bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get(); + bool shouldRegisterTree = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get(); + bool shouldRegisterBush = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BUSHES).Get(); - COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegister, EnWood02_RandomizerInit); + COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegisterTree || shouldRegisterBush, EnWood02_RandomizerInit); - COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegister, { + COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegisterTree || shouldRegisterBush, { EnWood02* treeActor = va_arg(args, EnWood02*); if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { EnWood02_RandomizerDraw(&treeActor->actor, gPlayState); } }); - COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegister, { + COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegisterTree, { EnWood02* treeActor = va_arg(args, EnWood02*); if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { EnWood02_RandomizerSpawnCollectible(treeActor, gPlayState); @@ -188,6 +190,25 @@ void RegisterShuffleTrees() { *should = false; } }); + + COND_VB_SHOULD(VB_BUSH_DROP_ITEM, shouldRegisterBush, { + EnWood02* treeActor = va_arg(args, EnWood02*); + if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { + return; + } + + EnItem00* item00 = + (EnItem00*)Item_DropCollectible2(gPlayState, &treeActor->actor.world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = treeIdentity->randomizerInf; + item00->itemEntry = + Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + treeIdentity->randomizerCheck = RC_UNKNOWN_CHECK; + treeActor->unk_14C = -0x15; + } + }); } void Rando::StaticData::RegisterTreeLocations() { @@ -201,7 +222,7 @@ void Rando::StaticData::RegisterTreeLocations() { locationTable[RC_HC_NEAR_GUARDS_TREE_4] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(421, 1397), "Tree Near Guards 4", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_4)); locationTable[RC_HC_NEAR_GUARDS_TREE_5] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-73, 1459), "Tree Near Guards 5", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_5)); locationTable[RC_HC_NEAR_GUARDS_TREE_6] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1494, 2108), "Tree Near Guards 6", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_6)); - locationTable[RC_HC_SKULLTULA_TREE] = Location::Tree(RC_HC_SKULLTULA_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-145, 2961), "HC GS Tree", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_SKULLTULA_TREE)); + locationTable[RC_HC_SKULLTULA_TREE] = Location::Tree(RC_HC_SKULLTULA_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-145, 2961), "GS Tree", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_SKULLTULA_TREE)); locationTable[RC_HC_GROTTO_TREE] = Location::Tree(RC_HC_GROTTO_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(924, 872), "Tree Near Storms Grotto", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GROTTO_TREE)); locationTable[RC_HC_NL_TREE_1] = Location::NLTree(RC_HC_NL_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-331, 1438), "NL Tree Near Guards 1", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_1)); locationTable[RC_HC_NL_TREE_2] = Location::NLTree(RC_HC_NL_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1022, 1444), "NL Tree Near Guards 2", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_2)); @@ -257,9 +278,74 @@ void Rando::StaticData::RegisterTreeLocations() { locationTable[RC_ZR_TREE] = Location::Tree(RC_ZR_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(-1690, 554), "Tree in Zoras River", RHT_TREE_ZORAS_RIVER, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_TREE)); locationTable[RC_KAK_TREE] = Location::Tree(RC_KAK_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-860, 522), "Kakariko GS Tree", RHT_TREE_KAKARIKO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_TREE)); locationTable[RC_LLR_TREE] = Location::Tree(RC_LLR_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(1309, -2241), "Lon Lon Ranch GS Tree", RHT_TREE_LON_LON_RANCH, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TREE)); + + locationTable[RC_HF_BUSH_NEAR_LAKE_1] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3506,13460), "Bush Near Lake 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_1)); + locationTable[RC_HF_BUSH_NEAR_LAKE_2] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3907,13119), "Bush Near Lake 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_2)); + locationTable[RC_HF_BUSH_NEAR_LAKE_3] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4106,13520), "Bush Near Lake 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_3)); + locationTable[RC_HF_BUSH_NEAR_LAKE_4] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4407,13320), "Bush Near Lake 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_4)); + locationTable[RC_HF_BUSH_NEAR_LAKE_5] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4486,13920), "Bush Near Lake 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_5)); + locationTable[RC_HF_BUSH_NEAR_LAKE_6] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4722,12732), "Bush Near Lake 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_6)); + locationTable[RC_HF_BUSH_NEAR_LAKE_7] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4723,13392), "Bush Near Lake 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_7)); + locationTable[RC_HF_BUSH_NEAR_LAKE_8] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5123,12391), "Bush Near Lake 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_8)); + locationTable[RC_HF_BUSH_NEAR_LAKE_9] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5322,12792), "Bush Near Lake 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_9)); + locationTable[RC_HF_BUSH_NEAR_LAKE_10] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5623,12592), "Bush Near Lake 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_10)); + locationTable[RC_HF_BUSH_NEAR_LAKE_11] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5702,13192), "Bush Near Lake 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_11)); + locationTable[RC_HF_NORTHERN_BUSH_1] = Location::Bush(RC_HF_NORTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4710,1381), "Northern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_1)); + locationTable[RC_HF_NORTHERN_BUSH_2] = Location::Bush(RC_HF_NORTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4711,2041), "Northern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_2)); + locationTable[RC_HF_NORTHERN_BUSH_3] = Location::Bush(RC_HF_NORTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5111,1040), "Northern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_3)); + locationTable[RC_HF_NORTHERN_BUSH_4] = Location::Bush(RC_HF_NORTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5310,1441), "Northern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_4)); + locationTable[RC_HF_NORTHERN_BUSH_5] = Location::Bush(RC_HF_NORTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5611,1241), "Northern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_5)); + locationTable[RC_HF_NORTHERN_BUSH_6] = Location::Bush(RC_HF_NORTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5690,1841), "Northern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_1] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3621,-303), "Child Northern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_1)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_2] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3622,356), "Child Northern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_2)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_3] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4022,-644), "Child Northern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_3)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_4] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4221,-243), "Child Northern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_4)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_5] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4522,-443), "Child Northern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_5)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_6] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4601,156), "Child Northern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_7] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4634,-284), "Child Northern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_7)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_8] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4713,315), "Child Northern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_8)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_9] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5014,115), "Child Northern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_9)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_10] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5213,516), "Child Northern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_10)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_11] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5614,175), "Child Northern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_11)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_1] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5792,7022), "Bush By Rocky Path 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_1)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_2] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5793,7682), "Bush By Rocky Path 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_2)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_3] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6193,6681), "Bush By Rocky Path 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_3)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_4] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6392,7082), "Bush By Rocky Path 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_4)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_5] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6693,6882), "Bush By Rocky Path 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_5)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_6] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6772,7482), "Bush By Rocky Path 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_6)); + locationTable[RC_HF_SOUTHERN_BUSH_1] = Location::Bush(RC_HF_SOUTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-270,12633), "Southern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_1)); + locationTable[RC_HF_SOUTHERN_BUSH_2] = Location::Bush(RC_HF_SOUTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-349,13233), "Southern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_2)); + locationTable[RC_HF_SOUTHERN_BUSH_3] = Location::Bush(RC_HF_SOUTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2,11473), "Southern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_3)); + locationTable[RC_HF_SOUTHERN_BUSH_4] = Location::Bush(RC_HF_SOUTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(229,12432), "Southern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_4)); + locationTable[RC_HF_SOUTHERN_BUSH_5] = Location::Bush(RC_HF_SOUTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(30,12833), "Southern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_5)); + locationTable[RC_HF_SOUTHERN_BUSH_6] = Location::Bush(RC_HF_SOUTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(382,11073), "Southern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_6)); + locationTable[RC_HF_SOUTHERN_BUSH_7] = Location::Bush(RC_HF_SOUTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(581,10672), "Southern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_7)); + locationTable[RC_HF_SOUTHERN_BUSH_8] = Location::Bush(RC_HF_SOUTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(629,13433), "Southern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_8)); + locationTable[RC_HF_SOUTHERN_BUSH_9] = Location::Bush(RC_HF_SOUTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(630,12773), "Southern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_9)); + locationTable[RC_HF_SOUTHERN_BUSH_10] = Location::Bush(RC_HF_SOUTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(81,10873), "Southern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_10)); + locationTable[RC_HF_SOUTHERN_BUSH_11] = Location::Bush(RC_HF_SOUTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(981,11673), "Southern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_11)); + locationTable[RC_HF_SOUTHERN_BUSH_12] = Location::Bush(RC_HF_SOUTHERN_BUSH_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(982,11013), "Southern Bush 12", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_12)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_1] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-873,13221), "Child Southern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_1)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_2] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-874,13881), "Child Southern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_2)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_3] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1009,11961), "Child Southern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_3)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_4] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1310,12161), "Child Southern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_4)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_5] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1509,11760), "Child Southern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_5)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_6] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1909,12761), "Child Southern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_7] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1910,12101), "Child Southern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_7)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_8] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(930,12561), "Child Southern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_8)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_9] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1274,12880), "Child Southern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_9)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_10] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1473,13281), "Child Southern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_10)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_11] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1774,13081), "Child Southern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_11)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_12] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1853,13681), "Child Southern Bush 12", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_12)); + locationTable[RC_ZF_BUSH_1] = Location::Bush(RC_ZF_BUSH_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(167,2514), "Bush 1", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_1)); + locationTable[RC_ZF_BUSH_2] = Location::Bush(RC_ZF_BUSH_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(394,2510), "Bush 2", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_2)); + locationTable[RC_ZF_BUSH_3] = Location::Bush(RC_ZF_BUSH_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(231,2406), "Bush 3", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_3)); + locationTable[RC_ZF_BUSH_4] = Location::Bush(RC_ZF_BUSH_4, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(544,2373), "Bush 4", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_4)); + locationTable[RC_ZF_BUSH_5] = Location::Bush(RC_ZF_BUSH_5, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(386,2265), "Bush 5", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_5)); + locationTable[RC_ZF_BUSH_6] = Location::Bush(RC_ZF_BUSH_6, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(551,2184), "Bush 6", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_6)); // clang-format on } -static ObjectExtension::Register RegisterPotIdentity; +static ObjectExtension::Register RegisterTreeIdentity; static RegisterShipInitFunc registerShuffleTrees(RegisterShuffleTrees, { "IS_RANDO" }); static RegisterShipInitFunc registerTreeLocations(Rando::StaticData::RegisterTreeLocations); diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 898c9ea389b..76130655570 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -30,6 +30,38 @@ Context::Context() { mLogic = std::make_shared(); mTrials = std::make_shared(); mFishsanity = std::make_shared(); + mSilverRupeeCounters = { + // Vanilla + SilverRupeeCounter(5, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, ICE_CAVERN, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, ICE_CAVERN, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, BOTTOM_OF_THE_WELL, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SPIRIT_GATE_SILVER_RUPEE, SPIRIT_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SPIRIT_BEAMOS_SILVER_RUPEE, SPIRIT_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SPIRIT_BOULDER_SILVER_RUPEE, SPIRIT_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SHADOW_SCYTHE_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_FOREST_TRIAL_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_FIRE_TRIAL_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_SPIRIT_TRIAL_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_VANILLA), + SilverRupeeCounter(5, RG_LIGHT_TRIAL_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_VANILLA), + // MQ + SilverRupeeCounter(5, RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_MQ), + SilverRupeeCounter(6, RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_MQ), + SilverRupeeCounter(3, RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, GERUDO_TRAINING_GROUND, RCQUEST_MQ), + SilverRupeeCounter(5, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, DODONGOS_CAVERN, RCQUEST_MQ), + SilverRupeeCounter(5, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, SPIRIT_TEMPLE, RCQUEST_MQ), + SilverRupeeCounter(5, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_MQ), + SilverRupeeCounter(10, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_MQ), + SilverRupeeCounter(5, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_MQ), + SilverRupeeCounter(10, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, SHADOW_TEMPLE, RCQUEST_MQ), + SilverRupeeCounter(5, RG_FIRE_TRIAL_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_MQ), + SilverRupeeCounter(5, RG_WATER_TRIAL_MQ_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_MQ), + SilverRupeeCounter(5, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, GANONS_CASTLE, RCQUEST_MQ), + }; VanillaLogicDefaults = { // RANDOTODO check what this does &mOptions[RSK_LINKS_POCKET], @@ -204,9 +236,11 @@ void Context::GenerateLocationPool() { (location.GetRCType() == RCTYPE_TREE && !mOptions[RSK_SHUFFLE_TREES]) || (location.GetRCType() == RCTYPE_NLTREE && (!mOptions[RSK_SHUFFLE_TREES] || mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC))) || + (location.GetRCType() == RCTYPE_BUSH && !mOptions[RSK_SHUFFLE_BUSHES]) || (location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) || - (location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES])) { + (location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES]) || + (location.GetRCType() == RCTYPE_SILVER_RUPEE && !mOptions[RSK_SHUFFLE_SILVER_RUPEES])) { continue; } if (location.IsOverworld()) { @@ -302,6 +336,10 @@ void Context::ItemReset() { GetItemLocation(RC_GIFT_FROM_RAURU)->ResetVariables(); GetItemLocation(RC_LINKS_POCKET)->ResetVariables(); + + for (auto silverCounter : mSilverRupeeCounters) { + silverCounter.SetCollected(0); + } } void Context::LocationReset() { @@ -552,6 +590,11 @@ void Context::SetHash(std::string hash) { mHash = std::move(hash); } +SilverRupeeCounter& Context::GetSilverRupeeCounter(RandomizerGet rg) { + assert(rg >= RG_SILVER_RUPEE_FIRST && rg <= RG_SILVER_RUPEE_LAST); + return mSilverRupeeCounters[rg - RG_SILVER_RUPEE_FIRST]; +} + const std::string& Context::GetSeedString() const { return mSeedString; } diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h index 96894775680..acfac670204 100644 --- a/soh/soh/Enhancements/randomizer/context.h +++ b/soh/soh/Enhancements/randomizer/context.h @@ -8,6 +8,7 @@ #include "hint.h" #include "fishsanity.h" #include "trial.h" +#include "ShuffleSilverRupees.h" #include #include @@ -175,12 +176,22 @@ class Context { */ void SetHash(std::string hash); + /** + * @brief Gets a reference to the silver rupee counter corresponding to the + * Given RandomizerGet value. + * + * @param rg + * @return SilverRupeeCounter& + */ + SilverRupeeCounter& GetSilverRupeeCounter(RandomizerGet rg); + private: static std::weak_ptr mContext; std::array hintTable = {}; std::array itemLocationTable = {}; std::array mOptions; std::array mTrickOptions; + std::array mSilverRupeeCounters; RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA; std::shared_ptr mEntranceShuffler; std::shared_ptr mDungeons; diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index b17718b6518..8c988ce4642 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -28,12 +28,15 @@ extern "C" { #include "objects/object_bv/object_bv.h" #include "objects/object_gnd/object_gnd.h" #include "objects/object_fd/object_fd.h" +#include "objects/object_mamenoki/object_mamenoki.h" #include "objects/object_mo/object_mo.h" #include "objects/object_sst/object_sst.h" #include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" +#include + extern PlayState* gPlayState; extern SaveContext gSaveContext; } @@ -116,6 +119,17 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawBeanSprout(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + Matrix_Scale(0.3f, 0.3f, 0.3f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMagicBeanSeedlingDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry) { s16 color_slot = getItemEntry->drawItemId - RG_DEKU_TREE_MAP; s16 colors[12][3] = { @@ -1109,6 +1123,22 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_OPA_DISP++, 255, 255, 255, 255); + gSPGrayscale(POLY_OPA_DISP++, true); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL); + gSPGrayscale(POLY_OPA_DISP++, false); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) { Vec3f pos; OPEN_DISPS(play->state.gfxCtx); @@ -1222,3 +1252,23 @@ extern "C" void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getIt CLOSE_DISPS(play->state.gfxCtx); } + +extern "C" void Randomizer_DrawSilverRupee(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + Color_RGB8 silverRupeeColor = + CVarGetColor24(CVAR_COSMETIC("Consumable.SilverRupee.Value"), Color_RGB8({ 255, 255, 255 })); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0x80, silverRupeeColor.r, silverRupeeColor.g, silverRupeeColor.b, 255); + gDPSetEnvColor(POLY_OPA_DISP++, silverRupeeColor.r / 5, silverRupeeColor.g / 5, silverRupeeColor.b / 5, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiRupeeInnerDL); + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, silverRupeeColor.r * 0.75f, silverRupeeColor.g * 0.75f, silverRupeeColor.b * 0.75f, + 255); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiRupeeOuterDL); + CLOSE_DISPS(play->state.gfxCtx); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 8483a7bf966..7c4c524fc6b 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -14,6 +14,7 @@ void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawBeanSprout(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry* getItemEntry); @@ -21,12 +22,14 @@ void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawSilverRupee(PlayState* play, GetItemEntry* getItemEntry); #define GET_ITEM_MYSTERY \ { \ diff --git a/soh/soh/Enhancements/randomizer/dungeon.cpp b/soh/soh/Enhancements/randomizer/dungeon.cpp index 1eb88ed73a9..4be5f4c4620 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/dungeon.cpp @@ -145,6 +145,22 @@ std::vector DungeonInfo::GetDungeonLocations() const { return locations; } +bool DungeonInfo::ContainsSilverRupee(RandomizerGet silverRupee) const { + auto dungeonLocations = GetDungeonLocations(); + const auto silverRupeeLocations = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) { + return StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SILVER_RUPEE; + }); + if (silverRupeeLocations.empty()) { + return false; + } + for (auto silverRupeeLocation : silverRupeeLocations) { + if (StaticData::GetLocation(silverRupeeLocation)->GetVanillaItem() == silverRupee) { + return true; + } + } + return false; +} + Dungeons::Dungeons() { dungeonList[DEKU_TREE] = DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DEKU_TREE, 0, 0, RSK_MQ_DEKU_TREE); diff --git a/soh/soh/Enhancements/randomizer/dungeon.h b/soh/soh/Enhancements/randomizer/dungeon.h index ba81d289d67..2d9dd575967 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.h +++ b/soh/soh/Enhancements/randomizer/dungeon.h @@ -38,6 +38,7 @@ class DungeonInfo { void PlaceVanillaCompass() const; void PlaceVanillaBossKey() const; void PlaceVanillaSmallKeys() const; + bool ContainsSilverRupee(RandomizerGet silverRupee) const; std::vector GetDungeonLocations() const; std::vector locations; diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 04ce7f1c8be..6a6cb13f7a2 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -863,6 +863,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l case VB_MIDO_CONSIDER_DEKU_TREE_DEAD: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); break; + case VB_OPEN_CHEST: + *should = *should && Flags_GetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + break; case VB_OPEN_KOKIRI_FOREST: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_CLOSED_FOREST_ON; @@ -2173,6 +2176,49 @@ void RandomizerOnActorInitHandler(void* actorRef) { return; } + if (RAND_GET_OPTION(RSK_SHUFFLE_BEAN_SOULS)) { + if (actor->id == ACTOR_OBJ_BEAN) { + RandomizerInf currentBeanSoulRandInf = RAND_INF_MAX; + switch (gPlayState->sceneNum) { + case SCENE_DEATH_MOUNTAIN_CRATER: + currentBeanSoulRandInf = RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL; + break; + case SCENE_DEATH_MOUNTAIN_TRAIL: + currentBeanSoulRandInf = RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL; + break; + case SCENE_DESERT_COLOSSUS: + currentBeanSoulRandInf = RAND_INF_DESERT_COLOSSUS_BEAN_SOUL; + break; + case SCENE_GERUDO_VALLEY: + currentBeanSoulRandInf = RAND_INF_GERUDO_VALLEY_BEAN_SOUL; + break; + case SCENE_GRAVEYARD: + currentBeanSoulRandInf = RAND_INF_GRAVEYARD_BEAN_SOUL; + break; + case SCENE_KOKIRI_FOREST: + currentBeanSoulRandInf = RAND_INF_KOKIRI_FOREST_BEAN_SOUL; + break; + case SCENE_LAKE_HYLIA: + currentBeanSoulRandInf = RAND_INF_LAKE_HYLIA_BEAN_SOUL; + break; + case SCENE_LOST_WOODS: + if ((actor->params & 0x3F) == 4) { + currentBeanSoulRandInf = RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL; + } else { + currentBeanSoulRandInf = RAND_INF_LOST_WOODS_BEAN_SOUL; + } + break; + case SCENE_ZORAS_RIVER: + currentBeanSoulRandInf = RAND_INF_ZORAS_RIVER_BEAN_SOUL; + break; + } + if (currentBeanSoulRandInf != RAND_INF_MAX && !Flags_GetRandomizerInf(currentBeanSoulRandInf)) { + Actor_Kill(actor); + return; + } + } + } + // If child is in the adult shooting gallery or adult in the child shooting gallery, then despawn the shooting // gallery man if (actor->id == ACTOR_EN_SYATEKI_MAN && RAND_GET_OPTION(RSK_SHUFFLE_INTERIOR_ENTRANCES) && diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index 13a654d9c22..79820a68c9c 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -23,7 +23,8 @@ enum ItemType { ITEMTYPE_REFILL, ITEMTYPE_SONG, ITEMTYPE_SHOP, - ITEMTYPE_DUNGEONREWARD + ITEMTYPE_DUNGEONREWARD, + ITEMTYPE_SILVERRUPEE }; namespace Rando { diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 3f6535c8326..a6ccb07b67c 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -317,6 +317,26 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); // Misc. + itemTable[RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL] = Item(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, Text{ "Death Mountain Crater Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL] = Item(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, Text{ "Death Mountain Trail Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_DESERT_COLOSSUS_BEAN_SOUL] = Item(RG_DESERT_COLOSSUS_BEAN_SOUL, Text{ "Desert Colossus Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_DESERT_COLOSSUS_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DESERT_COLOSSUS_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_GERUDO_VALLEY_BEAN_SOUL] = Item(RG_GERUDO_VALLEY_BEAN_SOUL, Text{ "Gerudo Valley Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_GERUDO_VALLEY_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GERUDO_VALLEY_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_GRAVEYARD_BEAN_SOUL] = Item(RG_GRAVEYARD_BEAN_SOUL, Text{ "Graveyard Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_GRAVEYARD_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GRAVEYARD_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_KOKIRI_FOREST_BEAN_SOUL] = Item(RG_KOKIRI_FOREST_BEAN_SOUL, Text{ "Kokiri Forest Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_KOKIRI_FOREST_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KOKIRI_FOREST_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_LAKE_HYLIA_BEAN_SOUL] = Item(RG_LAKE_HYLIA_BEAN_SOUL, Text{ "Lake Hylia Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_LAKE_HYLIA_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_LAKE_HYLIA_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_LOST_WOODS_BRIDGE_BEAN_SOUL] = Item(RG_LOST_WOODS_BRIDGE_BEAN_SOUL, Text{ "Lost Woods Bridge Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_LOST_WOODS_BRIDGE_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_LOST_WOODS_BRIDGE_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_LOST_WOODS_BEAN_SOUL] = Item(RG_LOST_WOODS_BEAN_SOUL, Text{ "Lost Woods Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_LOST_WOODS_BEAN_SOUL, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_LOST_WOODS_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); + itemTable[RG_ZORAS_RIVER_BEAN_SOUL] = Item(RG_ZORAS_RIVER_BEAN_SOUL, Text{ "Zora's River Bean Soul" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_NONE, RHT_BEAN_SOUL, RG_ZORAS_RIVER_BEAN_SOUL, OBJECT_GI_BEAN, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ZORAS_RIVER_BEAN_SOUL].SetCustomDrawFunc(Randomizer_DrawBeanSprout); itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "Âme de Gohma", "Gohmas Seele" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "Âme du Roi Dodongo", "König Dodongos Seele" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); @@ -349,9 +369,12 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); + itemTable[RG_OPEN_CHEST] = Item(RG_OPEN_CHEST, Text{ "Open Chests", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_KEY_SMALL, true, LOGIC_NONE, RHT_OPEN_CHEST, RG_OPEN_CHEST, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OPEN_CHEST].SetCustomDrawFunc(Randomizer_DrawOpenChest); + itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); @@ -372,6 +395,65 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE] = Item(RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, Text{ "Ice Cavern Spinning Blades Silver Rupee", "Ice Cavern Spinning Blades Silver Rupee", "Ice Cavern Spinning Blades Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_ICE_CAVERN_SILVER_RUPEE, RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_ICE_CAVERN_SLIDING_SILVER_RUPEE] = Item(RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, Text{ "Ice Cavern Block Sliding Silver Rupee", "Ice Cavern Block Sliding Silver Rupee", "Ice Cavern Block Sliding Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_ICE_CAVERN_SILVER_RUPEE, RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_SLIDING_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE] = Item(RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, Text{ "BotW Silver Rupee", "BotW Silver Rupee", "BotW Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_BOTTOM_OF_THE_WELL_SILVER_RUPEE, RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, Text{ "GTG Boulder Maze Silver Rupee", "GTG Boulder Maze Silver Rupee", "GTG Boulder Maze Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, Text{ "GTG Lava Room Silver Rupee", "GTG Lava Room Silver Rupee", "GTG Lava Room Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, Text{ "GTG Whirlpool Silver Rupee", "GTG Whirlpool Silver Rupee", "GTG Whirlpool Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_GATE_SILVER_RUPEE] = Item(RG_SPIRIT_GATE_SILVER_RUPEE, Text{ "Spirit Temple Child Gate Silver Rupee", "Spirit Temple Child Gate Silver Rupee", "Spirit Temple Child Gate Silver Rupee" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SPIRIT_TEMPLE_SILVER_RUPEE, RG_SPIRIT_GATE_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_GATE_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_BEAMOS_SILVER_RUPEE] = Item(RG_SPIRIT_BEAMOS_SILVER_RUPEE, Text{ "Spirit Temple Sun Block Room Silver Rupee", "Spirit Temple Sun Block Room Silver Rupee", "Spirit Temple Sun Block Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SPIRIT_TEMPLE_SILVER_RUPEE, RG_SPIRIT_BEAMOS_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_BEAMOS_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_BOULDER_SILVER_RUPEE] = Item(RG_SPIRIT_BOULDER_SILVER_RUPEE, Text{ "Spirit Temple Boulder Room Silver Rupee", "Spirit Temple Boulder Room Silver Rupee", "Spirit Temple Boulder Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SPIRIT_TEMPLE_SILVER_RUPEE, RG_SPIRIT_BOULDER_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_BOULDER_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_SCYTHE_SILVER_RUPEE] = Item(RG_SHADOW_SCYTHE_SILVER_RUPEE, Text{ "Shadow Temple Scythe Room Silver Rupee", "Shadow Temple Scythe Room Silver Rupee", "Shadow Temple Scythe Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_SCYTHE_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_SCYTHE_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE] = Item(RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, Text{ "Shadow Temple Near Falling Spikes Silver Rupee", "Shadow Temple Near Falling Spikes Silver Rupee", "Shadow Temple Near Falling Spikes Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE] = Item(RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, Text{ "Shadow Temple Invisible Spikes Room Silver Rupee", "Shadow Temple Invisible Spikes Room Silver Rupee", "Shadow Temple Invisible Spikes Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_FOREST_TRIAL_SILVER_RUPEE] = Item(RG_FOREST_TRIAL_SILVER_RUPEE, Text{ "Ganon's Castle Forest Trial Silver Rupee", "Ganon's Castle Forest Trial Silver Rupee", "Ganon's Castle Forest Trial Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_FOREST_TRIAL_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_FOREST_TRIAL_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_FIRE_TRIAL_SILVER_RUPEE] = Item(RG_FIRE_TRIAL_SILVER_RUPEE, Text{ "Ganon's Castle Fire Trial Silver Rupee", "Ganon's Castle Fire Trial Silver Rupee", "Ganon's Castle Fire Trial Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_FIRE_TRIAL_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_FIRE_TRIAL_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_TRIAL_SILVER_RUPEE] = Item(RG_SPIRIT_TRIAL_SILVER_RUPEE, Text{ "Ganon's Castle Spirit Trial Silver Rupee", "Ganon's Castle Spirit Trial Silver Rupee", "Ganon's Castle Spirit Trial Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_SPIRIT_TRIAL_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TRIAL_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_LIGHT_TRIAL_SILVER_RUPEE] = Item(RG_LIGHT_TRIAL_SILVER_RUPEE, Text{ "Ganon's Castle Light Trial Silver Rupee", "Ganon's Castle Light Trial Silver Rupee", "Ganon's Castle Light Trial Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_LIGHT_TRIAL_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_LIGHT_TRIAL_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE] = Item(RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, Text{ "Dodongo's Cavern Silver Rupee", "Dodongo's Cavern Silver Rupee", "Dodongo's Cavern Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_DODONGOS_CAVERN_SILVER_RUPEE, RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE] = Item(RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, Text{ "Shadow Temple MQ Spinning Scythes Silver Rupee", "Shadow Temple MQ Spinning Scythes Silver Rupee", "Shadow Temple MQ Spinning Scythes Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE] = Item(RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, Text{ "Shadow Temple MQ Invisible Scythes Silver Rupee", "Shadow Temple MQ Invisible Scythes Silver Rupee", "Shadow Temple MQ Invisible Scythes Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE] = Item(RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, Text{ "Shadow Temple MQ Near Falling Spikes Silver Rupee", "Shadow Temple MQ Near Falling Spikes Silver Rupee", "Shadow Temple MQ Near Falling Spikes Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE] = Item(RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, Text{ "Shadow Temple MQ Invisible Spike Room Silver Rupee", "Shadow Temple MQ Invisible Spike Room Silver Rupee", "Shadow Temple MQ Invisible Spike Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SHADOW_TEMPLE_SILVER_RUPEE, RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE] = Item(RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, Text{ "Spirit Temple MQ Lobby Silver Rupee", "Spirit Temple MQ Lobby Silver Rupee", "Spirit Temple MQ Lobby Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_SPIRIT_TEMPLE_SILVER_RUPEE, RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, Text{ "GTG MQ Boulder Maze Silver Rupee", "GTG MQ Boulder Maze Silver Rupee", "GTG MQ Boulder Maze Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, Text{ "GTG MQ Lava Room Silver Rupee", "GTG MQ Lava Room Silver Rupee", "GTG MQ Lava Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE] = Item(RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, Text{ "GTG MQ Whirlpool Room Silver Rupee", "GTG MQ Whirlpool Room Silver Rupee", "GTG MQ Whirlpool Room Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_FIRE_TRIAL_MQ_SILVER_RUPEE] = Item(RG_FIRE_TRIAL_MQ_SILVER_RUPEE, Text{ "Ganon's Castle Fire Trial MQ Silver Rupee", "Ganon's Castle Fire Trial MQ Silver Rupee", "Ganon's Castle Fire Trial MQ Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_FIRE_TRIAL_MQ_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_FIRE_TRIAL_MQ_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_WATER_TRIAL_MQ_SILVER_RUPEE] = Item(RG_WATER_TRIAL_MQ_SILVER_RUPEE, Text{ "Ganon's Castle Water Trial MQ Silver Rupee", "Ganon's Castle Water Trial MQ Silver Rupee", "Ganon's Castle Water Trial MQ Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_WATER_TRIAL_MQ_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_WATER_TRIAL_MQ_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_TRIAL_MQ_SILVER_RUPEE] = Item(RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, Text{ "Ganon's Castle Shadow Trial MQ Silver Rupee", "Ganon's Castle Shadow Trial MQ Silver Rupee", "Ganon's Castle Shadow Trial MQ Silver Rupee"}, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_GANONS_CASTLE_SILVER_RUPEE, RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TRIAL_MQ_SILVER_RUPEE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_BOTTOMLESS_SILVER_RUPEE_POUCH] = Item(RG_BOTTOMLESS_SILVER_RUPEE_POUCH, Text{ "Bottomless Silver Rupee Pouch", "Bottomless Silver Rupee Pouch", "Bottomless Silver Rupee Pouch" }, ITEMTYPE_SILVERRUPEE, 0, true, LOGIC_NONE, RHT_BOTTOMLESS_SILVER_RUPEE_POUCH, RG_BOTTOMLESS_SILVER_RUPEE_POUCH, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_SILVER_RUPEE, MOD_RANDOMIZER); + itemTable[RG_BOTTOMLESS_SILVER_RUPEE_POUCH].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_MAJOR); itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_LESSER); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index 847ee9aa991..250af2cfb74 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -585,6 +585,15 @@ Rando::Location Rando::Location::NLTree(RandomizerCheck rc, RandomizerCheckQuest false, collectionCheck }; } +Rando::Location Rando::Location::Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_BUSH, area_, ACTOR_EN_WOOD02, + scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, + false, collectionCheck }; +} + Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_) { return { rc, quest_, RCTYPE_GOSSIP_STONE, area_, ACTOR_EN_GS, diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index f118bdcda38..9556012204a 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -254,6 +254,10 @@ class Location { int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_, std::string&& spoilerName_); diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 0f517aa3ff5..8b468544ea4 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -511,8 +511,25 @@ Rando::Entrance* Region::GetExit(RandomizerRegion exitToReturn) { return nullptr; } -bool Region::CanPlantBeanCheck() const { - return Rando::Context::GetInstance()->GetLogic()->GetAmmo(ITEM_BEAN) > 0 && BothAgesCheck(); +bool Region::CanPlantBeanCheck(RandomizerGet bean) const { + auto ctx = Rando::Context::GetInstance(); + auto logic = ctx->GetLogic(); + + if (!logic->HasItem(bean)) { + // Never available without soul + return false; + } else if (ctx->GetOption(RSK_SKIP_PLANTING_BEANS) && + !ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) && + !ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) { + // All planted when skip enabled & bean pack not shuffled + return true; + } else if (logic->GetAmmo(ITEM_BEAN) <= 0) { + // Need bean pack + return false; + } else { + // BothAgesCheck necessary when planting + return ctx->GetOption(RSK_SKIP_PLANTING_BEANS) || BothAgesCheck(); + } } bool Region::AllAccountedFor() const { @@ -681,49 +698,49 @@ bool MQSpiritSharedBrokenWallRoom(const RandomizerRegion region, ConditionFn con return areaTable[region].MQSpiritShared(condition, true, anyAge); } -bool BeanPlanted(const RandomizerRegion region) { +bool BeanPlanted(const RandomizerGet bean) { // swchFlag found using the Actor Viewer to get the Obj_Bean parameters & 0x3F // not tested with multiple OTRs, but can be automated similarly to GetDungeonSmallKeyDoors SceneID sceneID; uint8_t swchFlag; - switch (region) { - case RR_ZORAS_RIVER: + switch (bean) { + case RG_ZORAS_RIVER_BEAN_SOUL: sceneID = SceneID::SCENE_ZORAS_RIVER; swchFlag = 3; break; - case RR_THE_GRAVEYARD: + case RG_GRAVEYARD_BEAN_SOUL: sceneID = SceneID::SCENE_GRAVEYARD; swchFlag = 3; break; - case RR_KOKIRI_FOREST: + case RG_KOKIRI_FOREST_BEAN_SOUL: sceneID = SceneID::SCENE_KOKIRI_FOREST; swchFlag = 9; break; - case RR_THE_LOST_WOODS: + case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: sceneID = SceneID::SCENE_LOST_WOODS; swchFlag = 4; break; - case RR_LW_BEYOND_MIDO: + case RG_LOST_WOODS_BEAN_SOUL: sceneID = SceneID::SCENE_LOST_WOODS; swchFlag = 18; break; - case RR_DEATH_MOUNTAIN_TRAIL: + case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: sceneID = SceneID::SCENE_DEATH_MOUNTAIN_TRAIL; swchFlag = 6; break; - case RR_LAKE_HYLIA: + case RG_LAKE_HYLIA_BEAN_SOUL: sceneID = SceneID::SCENE_LAKE_HYLIA; swchFlag = 1; break; - case RR_GERUDO_VALLEY: + case RG_GERUDO_VALLEY_BEAN_SOUL: sceneID = SceneID::SCENE_GERUDO_VALLEY; swchFlag = 3; break; - case RR_DMC_CENTRAL_LOCAL: + case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: sceneID = SceneID::SCENE_DEATH_MOUNTAIN_CRATER; swchFlag = 3; break; - case RR_DESERT_COLOSSUS: + case RG_DESERT_COLOSSUS_BEAN_SOUL: sceneID = SceneID::SCENE_DESERT_COLOSSUS; swchFlag = 24; break; @@ -747,8 +764,8 @@ bool BeanPlanted(const RandomizerRegion region) { return swch >> swchFlag & 1; } -bool CanPlantBean(const RandomizerRegion region) { - return areaTable[region].CanPlantBeanCheck() || BeanPlanted(region); +bool CanPlantBean(const RandomizerRegion region, const RandomizerGet bean) { + return areaTable[region].CanPlantBeanCheck(bean) || BeanPlanted(bean); } bool BothAges(const RandomizerRegion region) { diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h index d55928eea85..83ba46a6f0e 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -210,7 +210,7 @@ class Region { return hereVal; } - bool CanPlantBeanCheck() const; + bool CanPlantBeanCheck(RandomizerGet bean) const; bool AllAccountedFor() const; bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false); @@ -227,7 +227,7 @@ bool Here(const RandomizerRegion region, condition); // RANDOTODO make a less stupid way to check own at either age than self referencing with this bool MQSpiritSharedStatueRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge = false); bool MQSpiritSharedBrokenWallRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge = false); -bool CanPlantBean(const RandomizerRegion region); +bool CanPlantBean(const RandomizerRegion region, RandomizerGet bean); bool BothAges(const RandomizerRegion region); bool ChildCanAccess(const RandomizerRegion region); bool AdultCanAccess(const RandomizerRegion region); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 46a89f7af69..fb22e425f42 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -24,9 +24,9 @@ void RegionTable_Init_BottomOfTheWell() { EventAccess(LOGIC_BOTW_LOWERED_WATER, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->Get(LOGIC_BOTW_LOWERED_WATER)) || logic->CanUse(RG_BOOMERANG)), @@ -46,13 +46,13 @@ void RegionTable_Init_BottomOfTheWell() { //This region combines the Middle with the perimeter's hidden areas. If a warp puts link into the middle without crossing the perimeter or using lens, it will need it's own region areaTable[RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS] = Region("Bottom of the Well Behind Fake Walls", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), //You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick - LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), + LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), //Not technically behind a wall, but still logically needs lens due to pits - LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -75,7 +75,7 @@ void RegionTable_Init_BottomOfTheWell() { //Passing through this area needs lens, but entering doesn't, so that the fire keese can be killed without crossing the pits if enemy drops are ever shuffled areaTable[RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM] = Region("Bottom of the Well Keese-Beamos Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits @@ -87,7 +87,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE] = Region("Bottom of the Well Like-Like Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -120,8 +120,8 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), - LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //This assumes we spawned in dead hand's room, if whatever trick made this relevant instead puts us in the previous room, remove the kill Dead Hand check. @@ -130,20 +130,25 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT] = Region("Bottom of the Well Basement", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_11, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_12, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->BlastOrSmash() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_11, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_12, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5, true), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_3, logic->CanCutShrubs()), @@ -167,7 +172,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS] = Region("Bottom of the Well Basement Useful Bomb Flowers", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //Assumes RR_BOTTOM_OF_THE_WELL_BASEMENT access - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasItem(RG_GORONS_BRACELET) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->CanDetonateUprightBombFlower();}), @@ -244,7 +249,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, logic->HasExplosives() || (ctx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_2, logic->CanCutShrubs()), @@ -258,7 +263,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), //This location technically involves an invisible platform, but it's intended to do lensless in vanilla and is clearly signposted by pots. LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, true), //The enemies in this room are invisible and crowd around the player, being awkward to deal with blind unless you already know how. @@ -302,7 +307,7 @@ void RegionTable_Init_BottomOfTheWell() { //it is technically possible to get the chest before you get screamed at without rolling, but hard enough to be a trick if that is the requirement for something to be logical //With some kind of movement tech it's much easier, easy enough to be default logic, as the redeads don't lock on immediately in addition to the extra speed //leaving with no requirements for now but up for discussion. - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp index caa46d9c7e8..164aea46b16 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_1, logic->CanCutShrubs()), @@ -48,8 +48,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Region("Deku Tree Slingshot Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), - LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs() && logic->CanReflectNuts()), @@ -65,8 +65,8 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_COMPASS_CHEST, true), - LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_COMPASS_ROOM, logic->CanAttack()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_2, logic->CanCutShrubs()), @@ -82,7 +82,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), + LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)), LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_1, logic->CanCutShrubs()), @@ -215,7 +215,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_2F] = Region("Deku Tree MQ 2F", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_DEKU_TREE_MQ_LOBBY_HEART, true), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_6, logic->CanCutShrubs()), @@ -237,8 +237,8 @@ void RegionTable_Init_DekuTree() { }, { //Locations //Implies CanKillEnemy(RE_GOHMA_LARVA) - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA)), - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, (logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_HEART, true), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_2, logic->CanCutShrubs()), @@ -272,7 +272,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -298,7 +298,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_3, logic->CanCutShrubs()), @@ -334,7 +334,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_3, logic->CanCutShrubs()), @@ -351,7 +351,7 @@ void RegionTable_Init_DekuTree() { }, { //Locations //it blocks the chest while stunned unless you stun it from afar while it's slightly off the ground - LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_2, logic->CanCutShrubs()), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index c21a7a33eb8..06538e69194 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -27,7 +27,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return (Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST);), LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CallGossipFairy()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CanUse(RG_SONG_OF_STORMS)), @@ -146,7 +146,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_COMPASS_ROOM] = Region("Dodongos Cavern Compass Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET);}), @@ -160,7 +160,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Region("Dodongos Cavern Bomb Room Lower", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, true), LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), @@ -224,7 +224,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Region("Dodongos Cavern Bomb Room Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_2, logic->CanBreakPots()), }, { @@ -240,7 +240,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_LIFT_PLATFORM, []{return true;}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls()), + LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), @@ -284,7 +284,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku()), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()), }, { @@ -329,10 +329,16 @@ void RegionTable_Init_DodongosCavern() { //EventAccess(LOGIC_DC_CAN_CLIMB_STAIRS, []{return logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRS_WITH_BOW) && logic->CanUse(RG_FAIRY_BOW));}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_1, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_2, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_3, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_1, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_2, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_3, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()), + // RANDOTODO some of these are lower but some of these are actually in upper. + LOCATION(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5, true), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_2, logic->CanBreakCrates()), }, { @@ -381,7 +387,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, (logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -422,7 +428,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM] = Region("Dodongos Cavern MQ Larvae Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, true), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts + LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, logic->CanBreakCrates()), //implied logic->CanKillEnemy(RE_GOLD_SKULTULLA) based on entry reqs. Add crate logic when BONKO is added LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_2, logic->CanBreakCrates()), @@ -467,7 +473,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_CORNER_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanBreakPots()), }, { @@ -501,7 +507,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_POES_ROOM] = Region("Dodongos Cavern MQ Poes Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), //If you can get to the locked part of POES_ROOM without a way to open it or passing the chest, this will need it's own room + LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), //If you can get to the locked part of POES_ROOM without a way to open it or passing the chest, this will need it's own room LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);}) && //could be a seperate room if it gets busy logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG, true))), //Implies you can avoid/kill the enemies with what you use on the skull, if this assumption is broken, add //&& (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);}) || (logic->CanAvoidEnemy(RE_FIRE_KEESE) && logic->CanAvoidEnemy(RE_MAD_SCRUB))) @@ -556,7 +562,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, []{return logic->CanDetonateBombFlowers();}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), //pulling the grave isn't required, as you can open the chest through it + LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), //pulling the grave isn't required, as you can open the chest through it LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_2, logic->CanBreakPots()), @@ -608,7 +614,7 @@ void RegionTable_Init_DodongosCavern() { && logic->CanKillEnemy(RE_KING_DODONGO);}), }, { // Locations - LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), LOCATION(RC_KING_DODONGO, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index d7ae81645f1..8bc76124fd9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -30,7 +30,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FAIRY_POT, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_POT_1, (logic->CanBreakPots() && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))), LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_POT_2, (logic->CanBreakPots() && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))), LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_POT_3, (logic->CanBreakPots() && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))), @@ -58,7 +58,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Region("Fire Temple Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, (logic->HasExplosives() || logic->CanUse(RG_MEGATON_HAMMER)) && (logic->IsAdult || logic->CanGroundJump())), + LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, (logic->HasExplosives() || logic->CanUse(RG_MEGATON_HAMMER)) && (logic->IsAdult || logic->CanGroundJump()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return true;}), @@ -76,7 +76,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_GORON_ROOM] = Region("Fire Temple Loop Goron Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), @@ -105,7 +105,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON] = Region("Fire Temple Big Lava Room North Goron", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -122,7 +122,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON] = Region("Fire Temple Big Lava Room South Goron", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -149,7 +149,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Region("Fire Temple Shortcut Climb", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), @@ -158,7 +158,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Region("Fire Temple Boulder Maze Lower", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, logic->HasExplosives() && (logic->IsAdult || logic->HookshotOrBoomerang())), }, { //Exits @@ -170,7 +170,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM] = Region("Fire Temple Boulder Maze Lower Side Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return true;}), @@ -204,7 +204,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MAP_AREA] = Region("Fire Temple Map Region", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, []{return true;}), @@ -212,7 +212,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Region("Fire Temple Boulder Maze Upper", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return logic->HasExplosives();}), @@ -273,7 +273,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM] = Region("Fire Temple Fire Maze Side Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, []{return true;}), @@ -288,7 +288,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Region("Fire Temple West Central Upper", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return false;}), @@ -323,7 +323,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_WEST_PEAK] = Region("Fire Temple West Peak", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return logic->TakeDamage();}), @@ -373,7 +373,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH] = Region("Fire Temple MQ Map Room South", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, []{return logic->CanKillEnemy(RE_LIKE_LIKE);});}), @@ -411,7 +411,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER] = Region("Fire Temple MQ Lower Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && Here(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, []{return logic->CanKillEnemy(RE_FLARE_DANCER);})), + LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && Here(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, []{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, []{return true;}), @@ -429,7 +429,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE] = Region("Fire Temple MQ Map Room Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), @@ -439,7 +439,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM] = Region("Fire Temple MQ Near Boss Room", SCENE_FIRE_TEMPLE, {}, { //Locations //If we're using the south torch as the initial torch, or using FAs, we either have to cross to the north to remove the crate, or use a trick to ignore it - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->FireTimer() > 25 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->FireTimer() > 25 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_1, logic->FireTimer() > 25 && logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_2, logic->FireTimer() > 25 && logic->CanBreakCrates()), @@ -462,7 +462,7 @@ void RegionTable_Init_FireTemple() { //Fairies cannot be used for this as it is time sensetive, and NL is only useful with sticks as it disables other magic while in use, so it's tunic or raw damage taking ability. //testing tells me you take 3 ticks of lava damage, which is 12 internal damage or 3/4 of a heart at x1 damage multiplier, performing this run //logic->EffectiveHealth() works in half hearts for whatever reason, meaning this needs a deeper refactor to be perfect, but it should be good enough for now - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS))))))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS))))))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_2, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_1, logic->FireTimer() > 25 && logic->CanBreakCrates()), @@ -479,7 +479,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Region("Fire Temple MQ Big Lava Room", SCENE_FIRE_TEMPLE, {}, { //Locations //I'm currently assuming the oversight version of RT_FIRE_MQ_BK_CHEST for the fire timer logic - LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->FireTimer() >= 40 && logic->HasFireSource() && logic->HasExplosives() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && ctx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST)))), + LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->FireTimer() >= 40 && logic->HasFireSource() && logic->HasExplosives() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && ctx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST))) && logic->HasItem(RG_OPEN_CHEST)), //implies CanGetEnemyDrop(RE_GOLD_SKULLTULA) LOCATION(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, logic->FireTimer() >= 20 && logic->CanUse(RG_MEGATON_HAMMER)), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_ROOM_NORTH_POT, logic->CanBreakPots()), @@ -498,7 +498,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FAIRY_POT, []{return logic->CanUse(RG_HOOKSHOT);}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_1, logic->HookshotOrBoomerang()), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_2, logic->HookshotOrBoomerang()), }, { @@ -528,7 +528,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Region("Fire Temple MQ Lower Maze", SCENE_FIRE_TEMPLE, {}, { //Locations //Check handled on both floors - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives() && ctx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM)), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives() && ctx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, []{return true;}), @@ -540,7 +540,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE_CRATE_CAGE] = Region("Fire Temple MQ Lower Maze Crate Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_3, logic->CanBreakCrates()), @@ -565,14 +565,14 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE_BOX_CAGE] = Region("Fire Temple MQ Upper Maze Box Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_3, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_1, logic->CanBreakSmallCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_2, logic->CanBreakSmallCrates()), //Assumes maze access - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, []{return true;}), @@ -589,7 +589,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE] = Region("Fire Temple MQ Maze Shortcut Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);), + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->HasItem(RG_OPEN_CHEST);), LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_1, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_2, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_3, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT) && logic->CanBreakCrates()), @@ -716,7 +716,7 @@ void RegionTable_Init_FireTemple() { //Locations //This requires nothing in N64 logic, but is tight enough to need rollspam with the one-point on which is stricter than I would normally consider in logic //Child basically needs the scarecrow or a bunny hood though due to a worse ledge grab. - LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, logic->IsAdult || logic->CanUse(RG_SCARECROW)), + LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, (logic->IsAdult || logic->CanUse(RG_SCARECROW)) && logic->HasItem(RG_OPEN_CHEST)), }, { //The dropdown here is unusual in that it hits 1 of 3 locations: RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS and the section of RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS with the hammer switch //Using this dropdown is in N64 logic elsewhere, but not here, probably because it requires good foreknowlege to determine where to land diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp index a4a0563cfba..3f2f20893aa 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -18,7 +18,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FIRST_ROOM] = Region("Forest Temple First Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->IsAdult && logic->CanUse(RG_BOMB_BAG)) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslashExceptHammer() || (logic->IsChild && logic->CanUse(RG_BOMB_BAG))))), }, { //Exits @@ -67,7 +67,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_2, logic->CanBreakPots()), }, { @@ -116,7 +116,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && logic->CanUse(RG_BOOMERANG))), }, { //Exits @@ -132,7 +132,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->IsAdult && ctx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->IsAdult && ctx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return true;}), @@ -143,7 +143,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Region("Forest Temple Map Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE)), + LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, []{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->CanKillEnemy(RE_BLUE_BUBBLE);});}), @@ -152,7 +152,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_SEWER] = Region("Forest Temple Sewer", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8 && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), }, { @@ -163,7 +163,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_DRAINED_SEWER] = Region("Forest Temple Drained Well", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, true), LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { @@ -179,7 +179,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FLOORMASTER_ROOM] = Region("Forest Temple Floormaster Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage()), + LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return true;}), @@ -193,7 +193,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Region("Forest Temple Block Push Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))), + LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, []{return true;}), @@ -210,7 +210,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Region("Forest Temple NW Corridor Straightened", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), @@ -222,7 +222,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), @@ -231,7 +231,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_UPPER_STALFOS] = Region("Forest Temple Upper Stalfos", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -247,7 +247,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -282,8 +282,8 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Region("Forest Temple Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives()), - LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, []{return true;}), @@ -311,7 +311,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BOSS_REGION] = Region("Forest Temple Boss Region", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HookshotOrBoomerang()), }, { //Exits @@ -325,7 +325,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_LOBBY] = Region("Forest Temple MQ Lobby", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), //Implies CanPassEnemy(RE_BIG_SKULLTULA) LOCATION(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, logic->HookshotOrBoomerang()), }, { @@ -361,7 +361,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_2, logic->CanBreakPots()), }, { @@ -400,7 +400,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ After Block Puzzle", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), @@ -414,7 +414,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY] = Region("Forest Temple MQ Straight Hallway", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), @@ -429,7 +429,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return logic->CanHitSwitch();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART, true), LOCATION(RC_FOREST_TEMPLE_MQ_COURTYARD_MIDDLE_HEART, true), LOCATION(RC_FOREST_TEMPLE_MQ_COURTYARD_LEFT_HEART, true), @@ -462,7 +462,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_DEKU_BABA_NUTS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->CanHitEyeTargets() || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, (logic->CanHitEyeTargets() || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), //implies logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->CanHitEyeTargets() || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), @@ -478,7 +478,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES] = Region("Forest Temple MQ Outdoors Top Ledges", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Actually killing the skull from the doorframe with melee is annoying. Hammer swing hits low enough unaided, other swords need to crouch stab but the spot is precise based on range. kokiri sword doesn't reach at all for adult. LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, ((logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_FOREST_DOORFRAME))) && logic->CanJumpslash() && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_FAIRY_BOW) || logic->HookshotOrBoomerang() || (logic->CanStandingShield() && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD) || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD)))))), }, { @@ -491,7 +491,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE] = Region("Forest Temple MQ NE Outdoors Ledge", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Skipping swim here is non-trival, needs a roll-jump. If a swim lock is added it's probably wise to copy deku baba events here @@ -504,7 +504,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), @@ -517,7 +517,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -533,7 +533,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -561,7 +561,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_FALLING_ROOM] = Region("Forest Temple MQ Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, []{return true;}), @@ -587,7 +587,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_OPEN_BOSS_CORRIDOR, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, []{return logic->Get(LOGIC_FOREST_MEG);}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index 3f52a231cf6..dc206eecd74 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -57,9 +57,16 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_FOREST_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE));}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)), + LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_1, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT))))), LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_2, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT))))), + // RANDOTODO consider adding a new region here, since there will now be + // seven checks locked behind Fire Arrows or Din's Fire. + LOCATION(RC_FOREST_TRIAL_SILVER_RUPEE_1, true), + LOCATION(RC_FOREST_TRIAL_SILVER_RUPEE_2, true), + LOCATION(RC_FOREST_TRIAL_SILVER_RUPEE_3, true), + LOCATION(RC_FOREST_TRIAL_SILVER_RUPEE_4, true), + LOCATION(RC_FOREST_TRIAL_SILVER_RUPEE_5, true), }, {}); areaTable[RR_GANONS_CASTLE_FIRE_TRIAL] = Region("Ganon's Castle Fire Trial", SCENE_INSIDE_GANONS_CASTLE, { @@ -70,6 +77,13 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_POT_1, logic->CanBreakPots() && logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->CanUse(RG_LONGSHOT)), LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_POT_2, logic->CanBreakPots() && logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_GOLDEN_GAUNTLETS) && logic->CanUse(RG_LONGSHOT)), LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->CanUse(RG_GORON_TUNIC)), + // RANDOTODO consider a new region here, since collecting silver rupees out in + // the overworld will be required to reach the pots above. + LOCATION(RC_FIRE_TRIAL_SILVER_RUPEE_1, true), + LOCATION(RC_FIRE_TRIAL_SILVER_RUPEE_2, true), + LOCATION(RC_FIRE_TRIAL_SILVER_RUPEE_3, true), + LOCATION(RC_FIRE_TRIAL_SILVER_RUPEE_4, true), + LOCATION(RC_FIRE_TRIAL_SILVER_RUPEE_5, true), }, {}); areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", SCENE_INSIDE_GANONS_CASTLE, { @@ -79,8 +93,8 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_WATER_TRIAL_CLEAR, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_POT_1, logic->CanBreakPots() && logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_POT_2, logic->CanBreakPots() && logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_POT_3, logic->CanBreakPots() && logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD)), @@ -91,8 +105,8 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MEGATON_HAMMER) && ((logic->CanUse(RG_FIRE_ARROWS) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))))));}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_DINS_FIRE)))), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_DINS_FIRE)))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_POT_1, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_POT_2, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_POT_3, logic->CanBreakPots() && logic->CanUse(RG_MEGATON_HAMMER) && ((logic->CanUse(RG_FIRE_ARROWS) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))))))), @@ -108,12 +122,19 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SPIRIT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))))), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_1, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_2, ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_HEART, true), + // RANDOTODO new region here, some chests and pots will be locked behind collecting + // silver rupees from elsewhere now. Also one of these will require hookshot/a trick. + LOCATION(RC_SPIRIT_TRIAL_SILVER_RUPEE_1, true), + LOCATION(RC_SPIRIT_TRIAL_SILVER_RUPEE_2, true), + LOCATION(RC_SPIRIT_TRIAL_SILVER_RUPEE_3, true), + LOCATION(RC_SPIRIT_TRIAL_SILVER_RUPEE_4, true), + LOCATION(RC_SPIRIT_TRIAL_SILVER_RUPEE_5, true), }, {}); areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Region("Ganon's Castle Light Trial", SCENE_INSIDE_GANONS_CASTLE, { @@ -121,17 +142,24 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_LIGHT_TRIAL_CLEAR, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH));}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 1)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 1) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_POT_1, logic->CanBreakPots() && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2)), LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_1, logic->CanBreakPots() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_POT_2, logic->CanBreakPots() && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())) && logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), + // RANDOTODO new region to handle silver rupee collection logic for the pots past + // this puzzle. Also one of these will require hookshot. + LOCATION(RC_LIGHT_TRIAL_SILVER_RUPEE_1, true), + LOCATION(RC_LIGHT_TRIAL_SILVER_RUPEE_2, true), + LOCATION(RC_LIGHT_TRIAL_SILVER_RUPEE_3, true), + LOCATION(RC_LIGHT_TRIAL_SILVER_RUPEE_4, true), + LOCATION(RC_LIGHT_TRIAL_SILVER_RUPEE_5, true), }, {}); #pragma endregion @@ -196,8 +224,8 @@ void RegionTable_Init_GanonsCastle() { //If it is ever possible to warp into the RR_GANONS_CASTLE_MQ_FOREST_TRIAL_FINAL_ROOM, this needs splitting up as the requirements to reach things from the other side are more complex areaTable[RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM] = Region("Ganon's Castle MQ Forest Trial Beamos Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource()), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_STALFOS_ROOM, []{return true;}), @@ -216,7 +244,14 @@ void RegionTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM, []{return true;}), }); - areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_MAIN_ROOM] = Region("Ganon's Castle MQ Fire Trial Main Room", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { +areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_MAIN_ROOM] = Region("Ganon's Castle MQ Fire Trial Main Room", SCENE_INSIDE_GANONS_CASTLE, {}, { + // RANDOTODO logic + LOCATION(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_1, true), + LOCATION(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_2, true), + LOCATION(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_3, true), + LOCATION(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_4, true), + LOCATION(RC_FIRE_TRIAL_MQ_SILVER_RUPEE_5, true), + }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return true;}), //2 checks, 1 for the rupees, 1 for actually making it, as the rupees are permanent but throwing a pillar is not @@ -238,7 +273,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanJumpslash() || logic->HasExplosives();}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire()), + LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_HEART, logic->BlueFire()), }, { //Exits @@ -246,7 +281,14 @@ void RegionTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3) && Here(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->BlueFire();});}), }); - areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, {}, { + // RANDOTODO logic, most likely will need bottle/arrows to collect all, maybe hammer? + LOCATION(RC_WATER_TRIAL_MQ_SILVER_RUPEE_1, true), + LOCATION(RC_WATER_TRIAL_MQ_SILVER_RUPEE_2, true), + LOCATION(RC_WATER_TRIAL_MQ_SILVER_RUPEE_3, true), + LOCATION(RC_WATER_TRIAL_MQ_SILVER_RUPEE_4, true), + LOCATION(RC_WATER_TRIAL_MQ_SILVER_RUPEE_5, true), + }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3);}), //This assumes there's no way for child to have blue fire and not adult. @@ -279,7 +321,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Hookshot here is possible but very tight, but it's basically never relevant @@ -309,7 +351,14 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE] = Region("Ganon's Castle MQ Shadow Trial Far Side", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO logic for individual silver rupees, which probably also need to be moved + // to some of the other regions here rather than being all in one place. + LOCATION(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -341,7 +390,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle MQ Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}), @@ -350,12 +399,12 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_AFTER_SWITCH] = Region("Ganon's Castle MQ Spirit Trial After Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), //better names for these would be nice. - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH, []{return Here(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_AFTER_SWITCH, []{return logic->CanUse(RG_BOMBCHU_5);});}), @@ -384,7 +433,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_TRIFORCE_ROOM] = Region("Ganon's Castle MQ Light Trial Triforce Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return true;}), @@ -442,7 +491,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_TOWER_FLOOR_2] = Region("Ganon's Tower Floor 2", SCENE_GANONS_TOWER, {}, { //Locations - LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_TOWER_FLOOR_1, []{return Here(RR_GANONS_TOWER_FLOOR_2, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 6d75dffb663..83318bceeca 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -18,16 +18,25 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LOBBY] = Region("Gerudo Training Ground Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets()), - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets()), - LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), - LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART, true), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART, true), + // RANDOTODO move these to their own region, as one for the boulder maze + // currently does not exist. + LOCATION(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return true;}), + // RANDOTODO with silver rupees we can't necessarily get all the way to the heavy + // block room with this logic anymore, will likely need a middle region. Entrance(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && (logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT));}), Entrance(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, []{return Here(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true);});}), Entrance(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE, []{return true;}), @@ -35,11 +44,11 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9);}), @@ -47,8 +56,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT] = Region("Gerudo Training Ground Central Maze Right", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, true), }, { //Exits @@ -58,7 +67,19 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LAVA_ROOM] = Region("Gerudo Training Ground Lava Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24), + LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO invidual silver rupee logic, and also moving the check above to another + // region to handle silver rupee puzzle access logic. + LOCATION(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, []{return logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild;}), @@ -67,8 +88,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM] = Region("Gerudo Training Ground Hammer Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_FAIRY_BOW);}), @@ -77,7 +98,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER] = Region("Gerudo Training Ground Eye Statue Lower", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM, []{return true;}), @@ -85,7 +106,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER] = Region("Gerudo Training Ground Eye Statue Upper", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, []{return true;}), @@ -93,7 +114,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM] = Region("Gerudo Training Ground Heavy Block Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump()));}), @@ -102,10 +123,10 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM] = Region("Gerudo Training Ground Like Like Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, logic->CanJumpslashExceptHammer()), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), }, {}); #pragma endregion @@ -114,10 +135,10 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LOBBY] = Region("Gerudo Training Ground MQ Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1, logic->CanBreakPots()), @@ -134,7 +155,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_HIDDEN_ROOM] = Region("Gerudo Training Ground MQ Maze Hidden Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -142,7 +163,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK] = Region("Gerudo Training Ground MQ Maze First Lock", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 1);}), @@ -163,14 +184,22 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM] = Region("Gerudo Training Ground MQ Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEFT_SIDE, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), }); - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LEFT_SIDE] = Region("Gerudo Training Ground MQ Left Side", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LEFT_SIDE] = Region("Gerudo Training Ground MQ Left Side", SCENE_GERUDO_TRAINING_GROUND, {}, { + // RANDOTODO I think this is the silver rupee boulder room? Some of the entrance logic + // below might need to be changed to account for silver rupees. + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_3, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_4, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_5, true), + }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM, []{return true;}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_LEFT_SIDE, []{return logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_MQ_WITHOUT_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && logic->IsAdult && logic->CanJumpslash() && logic->CanUse(RG_HOOKSHOT));});}), @@ -182,7 +211,7 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Locations //implies logic->CanKillEnemy(RE_BIG_SKULLTULA) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && logic->CanUse(RG_SILVER_GAUNTLETS);}), @@ -192,7 +221,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK] = Region("Gerudo Training Ground MQ Behind Block", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_SPIKE) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD) && logic->HasItem(RG_OPEN_CHEST)), }, {}); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE] = Region("Gerudo Training Ground MQ Statue Room Ledge", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { @@ -205,7 +234,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM] = Region("Gerudo Training Ground MQ Magenta Fire Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return true;}), @@ -213,7 +242,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM] = Region("Gerudo Training Ground MQ Statue ROom", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return logic->CanUse(RG_LONGSHOT);}), @@ -223,8 +252,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM] = Region("Gerudo Training Ground MQ Torch Slug Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_TORCH_SLUG) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), @@ -255,7 +284,15 @@ void RegionTable_Init_GerudoTrainingGround() { //this region exists to place silver rupee items on later, normally it's all on fire and cannot be stood on without access from another area //This covers the platform that needs hover boots or the spawned targets to reach from any starting point other than RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT //the unshuffled rupee collection is handled by the event GTGPlatformSilverRupees - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM] = Region("Gerudo Training Ground MQ Furthest Platform", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM] = Region("Gerudo Training Ground MQ Furthest Platform", SCENE_GERUDO_TRAINING_GROUND, {}, { + // RANDOTODO double check on these silver rupees, some may need to go to other regions + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_3, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_4, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_5, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_6, true) + }, { //Exits //This is merely to extend this region's logic if you have hovers Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, []{return logic->CanUse(RG_HOVER_BOOTS);}), @@ -287,7 +324,11 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER] = Region("Gerudo Training Ground MQ Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //it is possible to snipe the stingers with bow or sling before dropping in, or just get really lucky, and avoid needing to take damage, but that might be trick worthy - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, (logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO double check this logic, might at least require Iron Boots. + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_1, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_2, true), + LOCATION(RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_3, true), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return true;}), @@ -299,8 +340,8 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -319,7 +360,7 @@ void RegionTable_Init_GerudoTrainingGround() { //is logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->CanKillEnemy(RE_ARMOS, ED_CLOSE, true, 1, true) broken down to exclude sticks, as it take too many to clear the room //Proper enemy kill room ammo logic is needed to handle this room //some combinations may be impossible without taking damage, keep an eye out for issues here - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, []{return Here(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM, []{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)));});}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index 823ff2eca2d..c9f6e9d53bf 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -30,10 +30,10 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump());}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && (logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump()))), - LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, logic->BlueFire()), - LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS)), - LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->IsAdult), + LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && (logic->IsAdult && logic->HasItem(RG_OPEN_CHEST) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->HasItem(RG_OPEN_CHEST)))), + LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->IsAdult && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ICE_CAVERN_FREESTANDING_POH, logic->BlueFire()), LOCATION(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, logic->HookshotOrBoomerang()), LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, logic->BlueFire() && logic->HookshotOrBoomerang()), @@ -53,6 +53,17 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG))), + // RANDOTODO might need a new region here for everything past the bars. + LOCATION(RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1, true), + LOCATION(RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2, true), + LOCATION(RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3, true), + LOCATION(RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4, true), + LOCATION(RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5, true), + LOCATION(RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_1, true), + LOCATION(RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_2, true), + LOCATION(RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_3, true), + LOCATION(RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_4, true), + LOCATION(RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_5, true), }, {}); #pragma endregion @@ -96,7 +107,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsChild || logic->CanJumpslash() || logic->HasExplosives();}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return logic->CanHitSwitch();})), + LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return logic->CanHitSwitch();}) && logic->HasItem(RG_OPEN_CHEST)), }, {}); areaTable[RR_ICE_CAVERN_MQ_SCARECROW_ROOM] = Region("Ice Cavern MQ Scarecrow Room", SCENE_ICE_CAVERN, {}, { @@ -122,8 +133,8 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_STALFOS_ROOM] = Region("Ice Cavern MQ Stalfos Room", SCENE_ICE_CAVERN, {}, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS)), - LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS)), + LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}), @@ -135,7 +146,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, true), + LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), //It is possible for child with master, BGS or sticks, or adult with BGS, to hit this switch through the ice with a crouchstab, but it's precise and unintuitive for a trick LOCATION(RC_ICE_CAVERN_MQ_FREESTANDING_POH, logic->HasExplosives()), //doing RT_ICE_MQ_RED_ICE_GS as child is untested, as I could not perform the trick reliably even as adult diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp index c473f676461..55357d5831a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -30,8 +30,8 @@ void RegionTable_Init_JabuJabusBelly() { //Locations LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku()), //We can kill the Stingers with ruto - LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F)), - LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE)), + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_1, logic->CanBreakSmallCrates()), LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_2, logic->CanBreakSmallCrates()), }, { @@ -97,7 +97,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_COMPASS_ROOM] = Region("Jabu Jabus Belly Compass Room", SCENE_JABU_JABU, {}, { //Locations //ruto could theoretically clear this room, but it's hard because of the timer and she doesn't appear with you when you respawn after failing, which would force a savewarp - LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM)), + LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return Here(RR_JABU_JABUS_BELLY_COMPASS_ROOM, []{return logic->CanKillEnemy(RE_SHABOM);});}), @@ -171,8 +171,8 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()), - LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_GRASS_1, logic->CanCutShrubs()), @@ -188,7 +188,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_LIFT_ROOM_COW, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_1, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_2, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_RUPEE_1, logic->CanUse(RG_IRON_BOOTS)), @@ -208,7 +208,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_HOLES_ROOM_DOOR, []{return true;}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, (logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_2, logic->CanBreakPots()), //Getting the ones closest to the ledge with rang may be a trick due to the awkward angle without blind shooting through the flesh @@ -222,8 +222,8 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM] = Region("Jabu Jabus Belly MQ Holes Room", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_PIT_GRASS_1, logic->CanCutShrubs() && logic->HasExplosives()), LOCATION(RC_JABU_JABUS_BELLY_MQ_PIT_GRASS_2, logic->CanCutShrubs() && logic->HasExplosives()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1, logic->CanCutShrubs()), @@ -240,9 +240,9 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM] = Region("Jabu Jabus Belly MQ Water Switch Room", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Implies logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_STINGER). Without swim, jump from the song of time block to the vines. - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_2, logic->CanBreakPots()), @@ -261,7 +261,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS, logic->CanCutShrubs()), @@ -326,7 +326,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE] = Region("Jabu Jabus Belly MQ Lift Room East Ledge", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, []{return true;}), @@ -338,7 +338,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_1, logic->CanCutShrubs()), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index 590af4d93de..c7e5243ad92 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -21,8 +21,8 @@ void RegionTable_Init_ShadowTemple() { EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_NEAR_DEAD_HAND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_WHISPERING_WALLS_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_WHISPERING_WALLS_POT_2, logic->CanBreakPots()), @@ -42,8 +42,14 @@ void RegionTable_Init_ShadowTemple() { EventAccess(LOGIC_FAIRY_POT, []{return true;}), //This fairy pot is only on 3DS }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO above logic needs to change/move to the silver rupee items below. + LOCATION(RC_SHADOW_SCYTHE_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_SCYTHE_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_SCYTHE_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_SCYTHE_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_SCYTHE_SILVER_RUPEE_5, true), LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, false), LOCATION(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { @@ -54,12 +60,24 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_HUGE_PIT] = Region("Shadow Temple Huge Pit", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanJumpslashExceptHammer()), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanJumpslashExceptHammer() && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO possibly new region here for silver rupee collection logic + LOCATION(RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, ((ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, ((ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, (logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH))) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO possible new regions to handle getting past silver rupee puzzle. + LOCATION(RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5, true), LOCATION(RC_SHADOW_TEMPLE_FREESTANDING_KEY, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2) && ((ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_BOMB_BAG) || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && logic->CanUse(RG_BOMBCHU_5)))), LOCATION(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, logic->CanJumpslashExceptHammer()), LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)) || (logic->IsAdult && logic->CanGroundJump())), @@ -79,9 +97,9 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Region("Shadow Temple Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)), - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives()), + LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1, logic->CanBreakPots()), @@ -95,9 +113,9 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Region("Shadow Temple Beyond Boat", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, logic->CanKillEnemy(RE_FLOORMASTER)), + LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, logic->CanKillEnemy(RE_FLOORMASTER) && logic->HasItem(RG_OPEN_CHEST)), //RANDOTODO check if child can reach the token LOCATION(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, logic->IsAdult && logic->CanAttack()), LOCATION(RC_SHADOW_TEMPLE_AFTER_BOAT_POT_1, logic->CanBreakPots()), @@ -144,9 +162,9 @@ void RegionTable_Init_ShadowTemple() { //Assumes we're in the "main" area and needed lens to enter. logic will need changes if a void warp puts us somewhere weird areaTable[RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA] = Region("Shadow Temple MQ Dead Hand Region", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), //There's a shared flag tied to some glass here. eye target here and killing an enemy group later in the dungeon toggles. I'm building the logic as "intended", assuming the switch needs flipping - LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && (logic->IsChild || logic->CanUse(RG_SONG_OF_TIME)) && logic->CanHitEyeTargets()), + LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && (logic->IsChild || logic->CanUse(RG_SONG_OF_TIME)) && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_POT_2, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_ENTRANCE_REDEAD_POT_1, logic->CanBreakPots()), @@ -160,7 +178,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Region("Shadow Temple MQ First Beamos", SCENE_SHADOW_TEMPLE, {}, { //Locations //Doing this sets the shared flag for the glass in RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, but doesn't seem to affect the chest - LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits @@ -170,7 +188,13 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)))), + LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO silver rupee logic + LOCATION(RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return Here(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));});}), @@ -179,7 +203,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH] = Region("Shadow Temple MQ Shortcut Path", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), @@ -210,11 +234,22 @@ void RegionTable_Init_ShadowTemple() { //you take half a heart base from a spit out, double check EffectiveHealth when damage logic gets reworked //Child is too small to get hit by the blades doesn't need the trick or lens for dodging them LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH))), + (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && + ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), + // RANDOTODO silver rupee logic + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return true;}), @@ -222,7 +257,13 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Region("Shadow Temple MQ Lower Huge Pit", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO silver rupee logic + LOCATION(RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM, []{return Here(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, []{return logic->CanJumpslash() || logic->HasExplosives();});}), @@ -231,7 +272,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM] = Region("Shadow Temple MQ Stone Umbrella Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || logic->CanGroundJump()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_WEST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_EAST_POT, logic->CanBreakPots()), @@ -245,8 +286,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA] = Region("Shadow Temple MQ Upper Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_NORTH_POT, logic->CanBreakPots()), @@ -268,7 +309,18 @@ void RegionTable_Init_ShadowTemple() { (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS));}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO silver rupee logic + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9, true), + LOCATION(RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, []{return logic->Get(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES);}), @@ -278,7 +330,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM] = Region("Shadow Temple MQ Stalfos Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return Here(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), @@ -293,7 +345,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WIND_HINT_ROOM] = Region("Shadow Temple MQ Wind Hint Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -306,8 +358,8 @@ void RegionTable_Init_ShadowTemple() { EventAccess(LOGIC_NUT_POT, []{return true;}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO)), - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, logic->HasExplosives()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_2, logic->CanBreakPots()), @@ -376,7 +428,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Region("Shadow Temple MQ Invisible Maze", SCENE_SHADOW_TEMPLE, {}, { //Locations //don't use CanDetonateUprightBombFlower as blue fire logic would need to account for player having multiple bottles & taking damage multiple times - LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, true), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_2, logic->CanBreakPots()), @@ -388,8 +440,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM] = Region("Shadow Temple MQ Spike Walls Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_BARICADE_POT, logic->CanBreakPots()), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 207b9c76f47..b7823d2cf6f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -32,9 +32,16 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_NUT_CRATE, []{return true;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), + // RANDOTODO silver rupee logic. Shouldn't need much here. Maybe could make each room a + // a region to simplify some of this other logic. + LOCATION(RC_SPIRIT_GATE_SILVER_RUPEE_1, true), + LOCATION(RC_SPIRIT_GATE_SILVER_RUPEE_2, true), + LOCATION(RC_SPIRIT_GATE_SILVER_RUPEE_3, true), + LOCATION(RC_SPIRIT_GATE_SILVER_RUPEE_4, true), + LOCATION(RC_SPIRIT_GATE_SILVER_RUPEE_5, true), LOCATION(RC_SPIRIT_TEMPLE_ANUBIS_POT_1, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), LOCATION(RC_SPIRIT_TEMPLE_ANUBIS_POT_2, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), LOCATION(RC_SPIRIT_TEMPLE_ANUBIS_POT_3, (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives() || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT))))), @@ -48,8 +55,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, (logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, (logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || (logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) || (logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || @@ -62,12 +69,19 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Region("Early Adult Spirit Temple", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY)), - LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslashExceptHammer())), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3)), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3)), + LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslashExceptHammer()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)))), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), + //RANDOTODO silver rupee logic. This one might actually be fine as is, other than maybe + // the chest after boulder room? + LOCATION(RC_SPIRIT_BOULDER_SILVER_RUPEE_1, true), + LOCATION(RC_SPIRIT_BOULDER_SILVER_RUPEE_2, true), + LOCATION(RC_SPIRIT_BOULDER_SILVER_RUPEE_3, true), + LOCATION(RC_SPIRIT_BOULDER_SILVER_RUPEE_4, true), + LOCATION(RC_SPIRIT_BOULDER_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 1);}), @@ -75,16 +89,22 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && - (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, (((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && + (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS)))) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || - (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), - LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && - (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, (((logic->HasExplosives() || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2)) && + (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS)))) || (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || - (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY)), - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), + (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))) && logic->HasItem(RG_OPEN_CHEST)), + // RANDOTODO silver rupee logic, may need some new regions here, not sure. + LOCATION(RC_SPIRIT_BEAMOS_SILVER_RUPEE_1, true), + LOCATION(RC_SPIRIT_BEAMOS_SILVER_RUPEE_2, true), + LOCATION(RC_SPIRIT_BEAMOS_SILVER_RUPEE_3, true), + LOCATION(RC_SPIRIT_BEAMOS_SILVER_RUPEE_4, true), + LOCATION(RC_SPIRIT_BEAMOS_SILVER_RUPEE_5, true), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 2))), @@ -111,8 +131,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTDOOR_HANDS] = Region("Spirit Temple Outdoor Hands", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, (logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)), - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives()), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, ((logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DESERT_COLOSSUS, []{return (logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)) || (logic->CanUse(RG_SILVER_GAUNTLETS) && ((logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)));}), @@ -120,9 +140,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Region("Spirit Temple Beyond Central Locked Door", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasExplosives()), - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives()), - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives()), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_BEAMOS_HALL_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, logic->HasExplosives() && logic->CanUse(RG_SUNS_SONG)), }, { @@ -132,9 +152,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Region("Spirit Temple Beyond Final Locked Door", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && ((logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT)))), - LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) && (logic->CanJumpslash() || logic->HasExplosives() || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOOKSHOT))))) || - (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), + LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && ((logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, ((logic->CanUse(RG_MIRROR_SHIELD) && (logic->CanJumpslash() || logic->HasExplosives() || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOOKSHOT))))) || + (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_LEFT_HEART, logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_RIGHT_HEART, logic->CanUse(RG_HOOKSHOT)), }, { @@ -154,14 +174,20 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Region("Spirit Temple MQ Lobby", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG)), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_3, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_4, logic->CanBreakPots()), + // RANDOTODO silver rupee logic, a couple of these might need to be in 1f west region. + LOCATION(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1, true), + LOCATION(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2, true), + LOCATION(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3, true), + LOCATION(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4, true), + LOCATION(RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5, true), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}), @@ -175,7 +201,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_SLUGMA_POT, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LEFT_HEART, logic->CanHitEyeTargets()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()), @@ -222,7 +248,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE);}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Stalfos room blocks you in with fire until you kill the stalfos, which won't spawn from behind the fire @@ -235,7 +261,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //The bridge is a temp flag, so not a way to cross south to north in logic @@ -245,7 +271,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH] = Region("Spirit Temple MQ West 1F Rusted Switch", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST);}), EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, {}, { //Exits @@ -267,10 +293,10 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM] = Region("Spirit Temple MQ Broken Wall Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, MQSpiritSharedBrokenWallRoom(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanKillEnemy(RE_BEAMOS);})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, MQSpiritSharedBrokenWallRoom(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanKillEnemy(RE_BEAMOS);}) && logic->HasItem(RG_OPEN_CHEST)), //Sunlights only temp spawn this chest, which is unintuitive/a bug. //chest is only reachable as adult glitchlessly, so we can skip the shared in favour of IsAdult as adult access is always Certain - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->IsAdult && (logic->HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->IsAdult && (logic->HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}), @@ -280,7 +306,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();}) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_EAST_POT, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return ((logic->IsAdult || logic->CanJumpslash()) && logic->CanUse(RG_BOOMERANG)) || ((logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) && logic->CanBreakPots());})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_WEST_POT, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) && logic->CanBreakPots());})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_CENTER_EAST_POT, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), @@ -304,7 +330,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM] = Region("Spirit Temple MQ Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations //We don't need Shared here because If we are checking as child, universe 2 adult access needs nothing so it always passes, and if we are checking as adult, it is Certain Access - LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_1, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), @@ -323,7 +349,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND] = Region("Spirit Temple MQ Silver Gauntlets Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //If it is ever relevent for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess @@ -342,7 +368,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH] = Region("Spirit Temple MQ Block Room North", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Does not need to be shared as it's hard child locked, because adult pushing the block is a permanent flag that blocks the eye target and cannot be undone - LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7) && logic->CanHitEyeTargets()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7) && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH from here is ever relevant, there needs to be an event to handle the block @@ -351,8 +377,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST] = Region("Spirit Temple MQ Statue Room East", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), @@ -404,7 +430,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM] = Region("Spirit Temple MQ Leever Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -420,7 +446,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM] = Region("Spirit Temple MQ After Symphony Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -429,7 +455,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM] = Region("Spirit Temple MQ Four Beamos Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits @@ -440,7 +466,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM] = Region("Spirit Temple MQ SoT Sun Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -463,7 +489,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Mirror Shield Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, []{return logic->CanUse(RG_LONGSHOT);}), @@ -473,7 +499,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM] = Region("Spirit Temple MQ 3F Gibdo Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}), @@ -530,7 +556,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE] = Region("Spirit Temple MQ Big Mirror Cave", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //If it's ever relevant to longshot into head from lobby, this needs to be an event access diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp index aee55c972a4..3c8c6bf8fe8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -55,7 +55,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MAP_ROOM] = Region("Water Temple Map Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 3)), + LOCATION(RC_WATER_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, []{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 3);}), @@ -63,7 +63,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CRACKED_WALL] = Region("Water Temple Cracked Wall", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, logic->HasExplosives()), + LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, []{return true;}), @@ -71,7 +71,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_TORCH_ROOM] = Region("Water Temple Torch Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3)), + LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, []{return logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3);}), @@ -124,7 +124,7 @@ void RegionTable_Init_WaterTemple() { EventAccess(LOGIC_FAIRY_POT, []{return true;}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_2, logic->CanBreakPots()), }, { @@ -152,7 +152,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Region("Water Temple Dragon Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOMBCHU_5))) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5)))) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)))), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOMBCHU_5))) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5)))) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_WEST_LOWER, []{return true;}), @@ -179,7 +179,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT] = Region("Water Temple Central Pillar Basement", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40), + LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, []{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16;}), @@ -187,7 +187,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_EAST_MIDDLE] = Region("Water Temple East Middle", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile()), + LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_2, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_3, logic->CanBreakPots()), @@ -212,7 +212,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_CORRIDOR] = Region("Water Temple Block Corridor", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_1, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_2, logic->CanBreakPots() && logic->HasItem(RG_GORONS_BRACELET) && (logic->Get(LOGIC_WATER_LOW_FROM_HIGH) || logic->Get(LOGIC_WATER_MIDDLE))), }, { @@ -247,7 +247,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_LONGSHOT_ROOM] = Region("Water Temple Longshot Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, true), + LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, []{return true;}), @@ -256,7 +256,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_RIVER] = Region("Water Temple River", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, logic->CanHitEyeTargets() && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_GS_RIVER, (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_WATER_RIVER_GS) && logic->CanUse(RG_LONGSHOT))), LOCATION(RC_WATER_TEMPLE_RIVER_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_RIVER_POT_2, logic->CanBreakPots()), @@ -264,7 +264,7 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_RIVER_HEART_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_WATER_TEMPLE_RIVER_HEART_3, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_WATER_TEMPLE_RIVER_HEART_4, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24) || logic->HasItem(RG_BRONZE_SCALE)), - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))) || ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))) || ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, []{return (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}), @@ -381,8 +381,8 @@ void RegionTable_Init_WaterTemple() { //EventAccess(LOGIC_WATER_LOW_FROM_MIDDLE, []{return false;}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->MQWaterLevel(WL_HIGH) && logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, (logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_HOOKSHOT)) || (logic->MQWaterLevel(WL_HIGH_OR_MID) && logic->CanOpenUnderwaterChest())), + LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->MQWaterLevel(WL_HIGH) && logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, ((logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_HOOKSHOT)) || (logic->MQWaterLevel(WL_HIGH_OR_MID) && logic->CanOpenUnderwaterChest())) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_MQ_LOWER_TORCHES_POT_1, (logic->MQWaterLevel(WL_LOW) && logic->CanBreakPots()) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 16)), LOCATION(RC_WATER_TEMPLE_MQ_LOWER_TORCHES_POT_2, (logic->MQWaterLevel(WL_LOW) && logic->CanBreakPots()) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 16)), }, { @@ -392,7 +392,7 @@ void RegionTable_Init_WaterTemple() { //Raising the targets by clearing this room achieves nothing logically because it requires WL_LOW to do and hookshot to use, which implies access to WL_MID and WL_HIGH already areaTable[RR_WATER_TEMPLE_MQ_EAST_TOWER_1F_ROOM] = Region("Water Temple MQ East Tower 1F Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->CanKillEnemy(RE_SPIKE)), + LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->CanKillEnemy(RE_SPIKE) && logic->HasItem(RG_OPEN_CHEST)), }, { Entrance(RR_WATER_TEMPLE_MQ_EAST_TOWER, []{return true;}), }); @@ -449,7 +449,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1_FINAL] = Region("Water Temple MQ Central Pillar B1 Final", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_LOWER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_LOWER_CRATE_3, logic->CanBreakCrates()), @@ -698,7 +698,7 @@ void RegionTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, []{return true;}), Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && Here(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanUse(RG_DINS_FIRE);});}), + Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && Here(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanUse(RG_DINS_FIRE);}) && logic->HasItem(RG_OPEN_CHEST);}), }); //this exists for the crates in preparation for clips through the grate @@ -717,7 +717,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -733,7 +733,7 @@ void RegionTable_Init_WaterTemple() { }, {}, { //Exits Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && (logic->MQWaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16));}), - Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && (logic->MQWaterLevel(WL_LOW) || logic->WaterTimer() >= 24);}) + Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && (logic->MQWaterLevel(WL_LOW) || logic->WaterTimer() >= 24) && logic->HasItem(RG_OPEN_CHEST);}) }); areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM] = Region("Water Temple MQ Triangle Torch Room", SCENE_WATER_TEMPLE, {}, diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index 15e80d6c261..89b12ca2689 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -66,7 +66,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_CENTRAL_NEARBY] = Region("DMC Central Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, { //Locations - LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, logic->IsAdult && logic->Hearts() >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, logic->IsAdult && logic->Hearts() >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) || (ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)))), LOCATION(RC_SHEIK_IN_CRATER, logic->IsAdult && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), }, { //Exits @@ -75,10 +75,10 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_CENTRAL_LOCAL] = Region("DMC Central Local", SCENE_DEATH_MOUNTAIN_CRATER, { //Events - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3);}), }, { //Locations - LOCATION(RC_DMC_GS_BEAN_PATCH, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->CanSpawnSoilSkull() && logic->CanAttack()), + LOCATION(RC_DMC_GS_BEAN_PATCH, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_DMC_NEAR_PLATFORM_RED_RUPEE, logic->IsChild), LOCATION(RC_DMC_MIDDLE_PLATFORM_RED_RUPEE, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_1, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), @@ -87,14 +87,14 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_4, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_5, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_6, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), }, { //Exits Entrance(RR_DMC_CENTRAL_NEARBY, []{return true;}), - Entrance(RR_DMC_LOWER_NEARBY, []{return (logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL)) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_DMC_UPPER_NEARBY, []{return logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL);}), + Entrance(RR_DMC_LOWER_NEARBY, []{return (logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DMC_UPPER_NEARBY, []{return logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL);}), Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return (logic->IsChild && logic->Hearts() >= 3 && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (logic->IsAdult && logic->FireTimer() >= 24);}), Entrance(RR_DMC_DISTANT_PLATFORM, []{return logic->FireTimer() >= 48 && logic->CanUse(RG_DISTANT_SCARECROW);}), }); @@ -109,7 +109,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_UPPER_GROTTO] = Region("DMC Upper Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMC_UPPER_GROTTO_CHEST, true), + LOCATION(RC_DMC_UPPER_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMC_UPPER_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index 42fa22cf946..e166842d64c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -7,25 +7,25 @@ void RegionTable_Init_DeathMountainTrail() { // clang-format off areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Region("Death Mountain", SCENE_DEATH_MOUNTAIN_TRAIL, { //Events - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), }, { //Locations - LOCATION(RC_DMT_CHEST, logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), - LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), + LOCATION(RC_DMT_CHEST, (logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), + LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash()), - LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash())) && logic->CanGetNightTimeGS()), + LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash())) && logic->CanGetNightTimeGS()), LOCATION(RC_DMT_BLUE_RUPEE, logic->IsChild && logic->BlastOrSmash()), LOCATION(RC_DMT_RED_RUPEE, logic->IsChild && logic->BlastOrSmash()), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_DMT_FLAG_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits Entrance(RR_KAK_BEHIND_GATE, []{return true;}), Entrance(RR_GORON_CITY, []{return true;}), - Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), + Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, []{return logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || logic->IsAdult;}), Entrance(RR_DMT_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); @@ -82,7 +82,7 @@ void RegionTable_Init_DeathMountainTrail() { areaTable[RR_DMT_STORMS_GROTTO] = Region("DMT Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMT_STORMS_GROTTO_CHEST, true), + LOCATION(RC_DMT_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMT_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp index 6f639d53953..7af296dcb92 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp @@ -11,13 +11,13 @@ void RegionTable_Init_DesertColossus() { EventAccess(LOGIC_BUG_ROCK, []{return true;}), }, { //Locations - LOCATION(RC_COLOSSUS_FREESTANDING_POH, logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS)), - LOCATION(RC_COLOSSUS_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), + LOCATION(RC_COLOSSUS_FREESTANDING_POH, logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS, RG_DESERT_COLOSSUS_BEAN_SOUL)), + LOCATION(RC_COLOSSUS_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_COLOSSUS_GS_TREE, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_COLOSSUS_GS_HILL, logic->IsAdult && ((CanPlantBean(RR_DESERT_COLOSSUS) && logic->CanAttack()) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_COLOSSUS_GS) && logic->CanUse(RG_HOOKSHOT))) && logic->CanGetNightTimeGS()), - LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_COLOSSUS_GS_HILL, logic->IsAdult && ((CanPlantBean(RR_DESERT_COLOSSUS, RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanAttack()) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_COLOSSUS_GS) && logic->CanUse(RG_HOOKSHOT))) && logic->CanGetNightTimeGS()), + LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_COLOSSUS_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_COLOSSUS_GOSSIP_STONE, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index 15f75ab8dd4..f21ab3cc2f1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -152,7 +152,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_NEAR_CHEST] = Region("GF Near Chest", SCENE_GERUDOS_FORTRESS, {}, { //Locations - LOCATION(RC_GF_CHEST, true), + LOCATION(RC_GF_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) && logic->CanGetNightTimeGS()), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index f613e969a0e..3a054692536 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -24,15 +24,15 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_UPPER_STREAM] = Region("GV Upper Stream", SCENE_GERUDO_VALLEY, { //Events EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS);}), }, { //Locations - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->HasItem(RG_BRONZE_SCALE)),//can use cucco as child - LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->HasItem(RG_BRONZE_SCALE) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)),//can use cucco as child + LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_GV_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_GV_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_GV_GOSSIP_STONE, true), @@ -68,7 +68,7 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_FORTRESS_SIDE] = Region("GV Fortress Side", SCENE_GERUDO_VALLEY, {}, { //Locations - LOCATION(RC_GV_CHEST, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_CHEST, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 2e4fa2fbe92..107106239a3 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -18,9 +18,9 @@ void RegionTable_Init_GoronCity() { (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))));}), }, { //Locations - LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), - LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_LEFT_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_CENTER_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_RIGHT_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))), LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))), LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 94a2c85c834..95046874fd0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -13,13 +13,13 @@ void RegionTable_Init_Graveyard() { EventAccess(LOGIC_BORROW_BUNNY_HOOD, []{return logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations - LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild && logic->AtNight), //TODO: This needs to change LOCATION(RC_GRAVEYARD_GS_WALL, logic->IsChild && logic->HookshotOrBoomerang() && logic->AtNight && logic->CanGetNightTimeGS()), - LOCATION(RC_GRAVEYARD_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), - LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GRAVEYARD_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GRAVEYARD_BEAN_SOUL) && logic->CanAttack()), + LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_GY_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_3, logic->CanCutShrubs()), @@ -32,7 +32,7 @@ void RegionTable_Init_Graveyard() { LOCATION(RC_GY_GRASS_10, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_11, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_12, logic->CanCutShrubs()), - LOCATION(RC_GRAVEYARD_CRATE, ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()), + LOCATION(RC_GRAVEYARD_CRATE, ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()), }, { //Exits Entrance(RR_GRAVEYARD_SHIELD_GRAVE, []{return logic->IsAdult || logic->AtNight;}), @@ -46,7 +46,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Region("Graveyard Shield Grave", SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, {}, { //Locations - LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, true), + LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -70,7 +70,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Region("Graveyard Heart Piece Grave", SCENE_REDEAD_GRAVE, {}, { //Locations - LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -78,7 +78,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", SCENE_ROYAL_FAMILYS_TOMB, {}, { //Locations - LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()), + LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()), LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -92,7 +92,7 @@ void RegionTable_Init_Graveyard() { EventAccess(LOGIC_DAMPES_WINDMILL_ACCESS, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}), }, { //Locations - LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), + LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)), LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()), LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp index b1cefc1444d..a1e03221f40 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_HauntedWasteland() { EventAccess(LOGIC_CARPET_MERCHANT, []{return logic->HasItem(RG_ADULT_WALLET) && CanBuyAnother(RC_WASTELAND_BOMBCHU_SALESMAN) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), }, { //Locations - LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource()), + LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)), LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang() || (logic->IsAdult && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 6c23dbcb840..d8722fa8681 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -110,6 +110,64 @@ void RegionTable_Init_HyruleField() { LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_5, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_6, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_TEKTITE_GROTTO_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_BUSH_NEAR_LAKE_1, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_2, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_3, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_4, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_5, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_6, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_7, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_8, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_9, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_10, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_11, true), + LOCATION(RC_HF_NORTHERN_BUSH_1, true), + LOCATION(RC_HF_NORTHERN_BUSH_2, true), + LOCATION(RC_HF_NORTHERN_BUSH_3, true), + LOCATION(RC_HF_NORTHERN_BUSH_4, true), + LOCATION(RC_HF_NORTHERN_BUSH_5, true), + LOCATION(RC_HF_NORTHERN_BUSH_6, true), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_1, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_2, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_3, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_4, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_5, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_6, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_7, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_8, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_9, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_10, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_11, logic->IsChild), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_1, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_2, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_3, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_4, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_5, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_6, true), + LOCATION(RC_HF_SOUTHERN_BUSH_1, true), + LOCATION(RC_HF_SOUTHERN_BUSH_2, true), + LOCATION(RC_HF_SOUTHERN_BUSH_3, true), + LOCATION(RC_HF_SOUTHERN_BUSH_4, true), + LOCATION(RC_HF_SOUTHERN_BUSH_5, true), + LOCATION(RC_HF_SOUTHERN_BUSH_6, true), + LOCATION(RC_HF_SOUTHERN_BUSH_7, true), + LOCATION(RC_HF_SOUTHERN_BUSH_8, true), + LOCATION(RC_HF_SOUTHERN_BUSH_9, true), + LOCATION(RC_HF_SOUTHERN_BUSH_10, true), + LOCATION(RC_HF_SOUTHERN_BUSH_11, true), + LOCATION(RC_HF_SOUTHERN_BUSH_12, true), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_1, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_2, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_3, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_4, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_5, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_6, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_7, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_8, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_9, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_10, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_11, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_12, logic->IsChild), }, { //Exits Entrance(RR_LW_BRIDGE, []{return true;}), @@ -131,7 +189,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_SOUTHEAST_GROTTO] = Region("HF Southeast Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, true), + LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_SOUTHEAST_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -149,7 +207,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_OPEN_GROTTO] = Region("HF Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_OPEN_GROTTO_CHEST, true), + LOCATION(RC_HF_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -203,7 +261,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_NEAR_MARKET_GROTTO] = Region("HF Near Market Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, true), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_NEAR_MARKET_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index cb6bb78a1c1..43b60374421 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -238,7 +238,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_REDEAD_GROTTO] = Region("Kak Redead Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2)), + LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), @@ -246,7 +246,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_OPEN_GROTTO] = Region("Kak Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KAK_OPEN_GROTTO_CHEST, true), + LOCATION(RC_KAK_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KAK_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 8c548745a79..7cdedbd7879 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -7,18 +7,18 @@ void RegionTable_Init_KokiriForest() { // clang-format off areaTable[RR_KOKIRI_FOREST] = Region("Kokiri Forest", SCENE_KOKIRI_FOREST, { //Events - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}), }, { //Locations - LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), + LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && logic->CanGetNightTimeGS()), - LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), + LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()), - LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_KF_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_KF_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_KF_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_KF_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_KF_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_BRIDGE_RUPEE, logic->IsChild), @@ -29,13 +29,13 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_NORTH_GRASS_EAST_RUPEE, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_1, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_2, logic->IsChild), - LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_KF_SARIAS_ROOF_WEST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_EAST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_NORTH_HEART, logic->IsChild), @@ -120,10 +120,10 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_MIDOS_HOUSE] = Region("KF Mido's House", SCENE_MIDOS_HOUSE, {}, { //Locations - LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, true), + LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KOKIRI_FOREST, []{return true;}), @@ -175,7 +175,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_STORMS_GROTTO] = Region("KF Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), + LOCATION(RC_KF_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index f88a2cb6a1c..15a6a07cca1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_LakeHylia() { areaTable[RR_LAKE_HYLIA] = Region("Lake Hylia", SCENE_LAKE_HYLIA, { //Events EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairy();}), - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), EventAccess(LOGIC_BUG_SHRUB, []{return logic->IsChild && logic->CanCutShrubs();}), EventAccess(LOGIC_CHILD_SCARECROW, []{return logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}), @@ -17,17 +17,17 @@ void RegionTable_Init_LakeHylia() { //Locations LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)), LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->Get(LOGIC_WATER_TEMPLE_CLEAR) && logic->HasItem(RG_BRONZE_SCALE)) || logic->CanUse(RG_DISTANT_SCARECROW)) && logic->CanUse(RG_FAIRY_BOW)), - LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA))), - LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), + LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL))), + LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->CanGetNightTimeGS() && logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_LH_GS_TREE, logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->CanGetNightTimeGS()), LOCATION(RC_LH_FRONT_RUPEE, logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_LH_MIDDLE_RUPEE, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LH_BACK_RUPEE, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), - LOCATION(RC_LH_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LH_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LH_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LH_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LH_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LH_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LH_LAB_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_LH_LAB_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), //You can walk along the edge of the lake to get these without swimming, the fairy is created going backwards, which is convenient here @@ -86,7 +86,7 @@ void RegionTable_Init_LakeHylia() { Entrance(RR_HYRULE_FIELD, []{return true;}), Entrance(RR_LH_FROM_SHORTCUT, []{return true;}), Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}), - Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}), + Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)));}), Entrance(RR_LH_LAB, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}), Entrance(RR_LH_FROM_WATER_TEMPLE, []{return true;}), Entrance(RR_LH_GROTTO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index dc6d84875eb..aa5d535e5bc 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -13,8 +13,8 @@ void RegionTable_Init_LostWoods() { areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", SCENE_LOST_WOODS, { //Events EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(LOGIC_BUG_SHRUB, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(LOGIC_BUG_SHRUB, []{return logic->IsChild && logic->CanCutShrubs();}), EventAccess(LOGIC_BORROW_SPOOKY_MASK, []{return logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations @@ -33,7 +33,7 @@ void RegionTable_Init_LostWoods() { LOCATION(RC_LW_OCARINA_MEMORY_GAME, logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 5), LOCATION(RC_LW_TARGET_IN_WOODS, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)), LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku()), - LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanSpawnSoilSkull() && logic->CanAttack()), + LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanSpawnSoilSkull(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanAttack()), //RANDOTODO handle collecting some of these as you leave the shortcut from the other side LOCATION(RC_LW_SHORTCUT_RUPEE_1, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LW_SHORTCUT_RUPEE_2, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), @@ -43,9 +43,9 @@ void RegionTable_Init_LostWoods() { LOCATION(RC_LW_SHORTCUT_RUPEE_6, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LW_SHORTCUT_RUPEE_7, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LW_SHORTCUT_RUPEE_8, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LW_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_LW_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LW_SHORTCUT_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), @@ -57,7 +57,7 @@ void RegionTable_Init_LostWoods() { //Exits Entrance(RR_LW_FOREST_EXIT, []{return true;}), Entrance(RR_GC_WOODS_WARP, []{return true;}), - Entrance(RR_LW_BRIDGE, []{return (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_LW_BRIDGE, []{return (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS, RG_LOST_WOODS_BRIDGE_BEAN_SOUL) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), Entrance(RR_LW_BEYOND_MIDO, []{return logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}), Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, []{return Here(RR_THE_LOST_WOODS, []{return logic->BlastOrSmash();});}), @@ -65,17 +65,18 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_BEYOND_MIDO] = Region("LW Beyond Mido", SCENE_LOST_WOODS, { //Events - EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_BEAN_PLANT_FAIRY, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS);}), }, { //Locations LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku()), LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku()), - LOCATION(RC_LW_GS_ABOVE_THEATER, logic->IsAdult && ((CanPlantBean(RR_LW_BEYOND_MIDO) && logic->CanAttack()) || (ctx->GetTrickOption(RT_LW_GS_BEAN) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE)))) && logic->CanGetNightTimeGS()), - LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, logic->CanSpawnSoilSkull() && (logic->CanAttack() || (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->CanReflectNuts()))), + LOCATION(RC_LW_GS_ABOVE_THEATER, logic->IsAdult && ((CanPlantBean(RR_LW_BEYOND_MIDO, RG_LOST_WOODS_BEAN_SOUL) && logic->CanAttack()) || (ctx->GetTrickOption(RT_LW_GS_BEAN) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE)))) && logic->CanGetNightTimeGS()), + LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, logic->CanSpawnSoilSkull(RG_LOST_WOODS_BEAN_SOUL) && (logic->CanAttack() || (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->CanReflectNuts()))), LOCATION(RC_LW_BOULDER_RUPEE, logic->BlastOrSmash()), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_1, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_2, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BEAN_SPROUT_NEAR_THEATER_FAIRY_3, logic->IsChild && logic->HasItem(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LW_GRASS_4, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_5, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_6, logic->CanCutShrubs()), @@ -93,7 +94,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Region("LW Near Shortcuts Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, true), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 982601b3c03..70fed912fb0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -193,17 +193,17 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Region("Market Treasure Chest Game", SCENE_TREASURE_BOX_SHOP, {}, { //Locations LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET)), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), }, { //Exits Entrance(RR_THE_MARKET, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp index 34425e22987..855e5173c05 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp @@ -57,7 +57,7 @@ void RegionTable_Init_SacredForestMeadow() { areaTable[RR_SFM_WOLFOS_GROTTO] = Region("SFM Wolfos Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SFM_ENTRYWAY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp index 5202e7fff46..1c6d822e4b8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -16,7 +16,7 @@ void RegionTable_Init_ZorasDomain() { }, { //Locations LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), - LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS)), + LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED)), LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->CanUse(RG_PRESCRIPTION)), LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && (logic->HookshotOrBoomerang() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_MAGIC_SINGLE) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (ctx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 0a8a1d2bc84..20a22334245 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_ZorasFountain() { areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", SCENE_ZORAS_FOUNTAIN, { //Events EventAccess(LOGIC_GOSSIP_STONE_FAIRY, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), + EventAccess(LOGIC_BUTTERFLY_FAIRY, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), }, { //Locations LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees()), @@ -24,6 +24,12 @@ void RegionTable_Init_ZorasFountain() { LOCATION(RC_ZF_NEAR_JABU_POT_3, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_NEAR_JABU_POT_4, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZF_BUSH_1, logic->IsChild), + LOCATION(RC_ZF_BUSH_2, logic->IsChild), + LOCATION(RC_ZF_BUSH_3, logic->IsChild), + LOCATION(RC_ZF_BUSH_4, logic->IsChild), + LOCATION(RC_ZF_BUSH_5, logic->IsChild), + LOCATION(RC_ZF_BUSH_6, logic->IsChild), }, { //Exits Entrance(RR_ZD_BEHIND_KING_ZORA, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index bfd228523d9..060591b7987 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -86,7 +86,7 @@ void RegionTable_Init_ZoraRiver() { areaTable[RR_ZR_OPEN_GROTTO] = Region("ZR Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), + LOCATION(RC_ZR_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZR_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index fd578d7dee3..0b98fb19057 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -134,6 +134,17 @@ bool Logic::HasItem(RandomizerGet itemName) { case RG_OCARINA_C_RIGHT_BUTTON: case RG_OCARINA_C_DOWN_BUTTON: case RG_OCARINA_C_UP_BUTTON: + // Bean Souls + case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: + case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: + case RG_DESERT_COLOSSUS_BEAN_SOUL: + case RG_GERUDO_VALLEY_BEAN_SOUL: + case RG_GRAVEYARD_BEAN_SOUL: + case RG_KOKIRI_FOREST_BEAN_SOUL: + case RG_LAKE_HYLIA_BEAN_SOUL: + case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: + case RG_LOST_WOODS_BEAN_SOUL: + case RG_ZORAS_RIVER_BEAN_SOUL: // Boss Souls case RG_GOHMA_SOUL: case RG_KING_DODONGO_SOUL: @@ -215,6 +226,8 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_WALLET) >= 2; case RG_TYCOON_WALLET: return CurrentUpgrade(UPG_WALLET) >= 3; + case RG_OPEN_CHEST: + return CheckRandoInf(RAND_INF_CAN_OPEN_CHEST); // Scales case RG_BRONZE_SCALE: return CheckRandoInf(RAND_INF_CAN_SWIM); @@ -1172,8 +1185,8 @@ bool Logic::BlastOrSmash() { return HasExplosives() || CanUse(RG_MEGATON_HAMMER); } -bool Logic::CanSpawnSoilSkull() { - return IsChild && CanUse(RG_BOTTLE_WITH_BUGS); +bool Logic::CanSpawnSoilSkull(RandomizerGet bean) { + return IsChild && CanUse(RG_BOTTLE_WITH_BUGS) && HasItem(bean); } bool Logic::CanReflectNuts() { @@ -1401,6 +1414,16 @@ std::map Logic::RandoGetToRandInf = { { RG_ZELDAS_LETTER, RAND_INF_ZELDAS_LETTER }, { RG_WEIRD_EGG, RAND_INF_WEIRD_EGG }, { RG_RUTOS_LETTER, RAND_INF_OBTAINED_RUTOS_LETTER }, + { RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL }, + { RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL }, + { RG_DESERT_COLOSSUS_BEAN_SOUL, RAND_INF_DESERT_COLOSSUS_BEAN_SOUL }, + { RG_GERUDO_VALLEY_BEAN_SOUL, RAND_INF_GERUDO_VALLEY_BEAN_SOUL }, + { RG_GRAVEYARD_BEAN_SOUL, RAND_INF_GRAVEYARD_BEAN_SOUL }, + { RG_KOKIRI_FOREST_BEAN_SOUL, RAND_INF_KOKIRI_FOREST_BEAN_SOUL }, + { RG_LAKE_HYLIA_BEAN_SOUL, RAND_INF_LAKE_HYLIA_BEAN_SOUL }, + { RG_LOST_WOODS_BRIDGE_BEAN_SOUL, RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL }, + { RG_LOST_WOODS_BEAN_SOUL, RAND_INF_LOST_WOODS_BEAN_SOUL }, + { RG_ZORAS_RIVER_BEAN_SOUL, RAND_INF_ZORAS_RIVER_BEAN_SOUL }, { RG_GOHMA_SOUL, RAND_INF_GOHMA_SOUL }, { RG_KING_DODONGO_SOUL, RAND_INF_KING_DODONGO_SOUL }, { RG_BARINADE_SOUL, RAND_INF_BARINADE_SOUL }, @@ -1571,6 +1594,9 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_CLAIM_CHECK: SetRandoInf(randoGet - RG_COJIRO + RAND_INF_ADULT_TRADES_HAS_COJIRO, state); break; + case RG_OPEN_CHEST: + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, state); + break; case RG_PROGRESSIVE_HOOKSHOT: { uint8_t i; for (i = 0; i < 3; i++) { @@ -1767,6 +1793,16 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_RUTOS_LETTER: SetRandoInf(RAND_INF_OBTAINED_RUTOS_LETTER, state); break; + case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: + case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: + case RG_DESERT_COLOSSUS_BEAN_SOUL: + case RG_GERUDO_VALLEY_BEAN_SOUL: + case RG_GRAVEYARD_BEAN_SOUL: + case RG_KOKIRI_FOREST_BEAN_SOUL: + case RG_LAKE_HYLIA_BEAN_SOUL: + case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: + case RG_LOST_WOODS_BEAN_SOUL: + case RG_ZORAS_RIVER_BEAN_SOUL: case RG_GOHMA_SOUL: case RG_KING_DODONGO_SOUL: case RG_BARINADE_SOUL: @@ -2308,6 +2344,11 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, true); } + // If we're not shuffling open chest, we start with it + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST).Is(false)) { + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, true); + } + // If we're not shuffling child's wallet, we start with it if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) { SetRandoInf(RAND_INF_HAS_WALLET, true); @@ -2318,6 +2359,19 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_FISHING_POLE_FOUND, true); } + if (ctx->GetOption(RSK_SHUFFLE_BEAN_SOULS).Is(false)) { + SetRandoInf(RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, true); + SetRandoInf(RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, true); + SetRandoInf(RAND_INF_DESERT_COLOSSUS_BEAN_SOUL, true); + SetRandoInf(RAND_INF_GERUDO_VALLEY_BEAN_SOUL, true); + SetRandoInf(RAND_INF_GRAVEYARD_BEAN_SOUL, true); + SetRandoInf(RAND_INF_KOKIRI_FOREST_BEAN_SOUL, true); + SetRandoInf(RAND_INF_LAKE_HYLIA_BEAN_SOUL, true); + SetRandoInf(RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL, true); + SetRandoInf(RAND_INF_LOST_WOODS_BEAN_SOUL, true); + SetRandoInf(RAND_INF_ZORAS_RIVER_BEAN_SOUL, true); + } + // If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in // vanilla FiT if (!IsFireLoopLocked() && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 508db91ba47..4972835aabb 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -74,7 +74,7 @@ class Logic { bool BlueFire(); bool HasExplosives(); bool BlastOrSmash(); - bool CanSpawnSoilSkull(); + bool CanSpawnSoilSkull(RandomizerGet bean); bool CanReflectNuts(); bool CanCutShrubs(); bool CanStunDeku(); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index c544d3b2904..58ec8f1fa5d 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -253,6 +253,7 @@ void Settings::CreateOptionDescriptions() { "\n" "If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n" "If you void out in Water Temple you will immediately be kicked out to prevent a softlock."; + mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST] = "Shuffles the ability to open chests into the item pool."; mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" @@ -297,6 +298,8 @@ void Settings::CreateOptionDescriptions() { "Trees will have a special appearance when carrying randomized items.\n" "\nSome trees are dependant on Link's age, such as some trees in Hyrule Field.\nTwo trees at Hyrule Castle are " "only shuffle with No Logic."; + mOptionDescriptions[RSK_SHUFFLE_BUSHES] = + "Bushes in Hyrule Field & Zora's Fountain will contain randomized items when first walked through."; mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; @@ -625,6 +628,9 @@ void Settings::CreateOptionDescriptions() { "Start with the ability to summon Pierre the Scarecrow. Pulling out an Ocarina in the usual locations will " "automatically summon him.\n" "With \"Shuffle Ocarina Buttons\" enabled, you'll need at least two Ocarina buttons to summon him."; + mOptionDescriptions[RSK_SKIP_PLANTING_BEANS] = "Beans will be planted.\n" + "If beans are shuffled, you must find beans first.\n" + "If bean souls are shuffled, you must find soul first."; mOptionDescriptions[RSK_ITEM_POOL] = "Sets how many major items appear in the item pool.\n" "\n" "Plentiful - Extra major items are added to the pool.\n" @@ -770,9 +776,22 @@ void Settings::CreateOptionDescriptions() { "location is reachable. When disabled, only " "required items and locations to beat the game " "will be guaranteed reachable."; + mOptionDescriptions[RSK_SHUFFLE_BEAN_SOULS] = + "Shuffle 10 bean souls which must be found to spawn corresponding soil / plant."; mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS] = "Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its " "respective soul." "\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul."; + mOptionDescriptions[RSK_SHUFFLE_SILVER_RUPEES] = + "THIS OPTION DOES NOT CURRENTLY HAVE ANY LOGIC ! ! ! " + "\n" + "Shuffle Silver Rupees out of their usual locations in dungeons. " + "\n" + "They will be replaced with new items and can be found at other locations in the game. The doors they " + "previously controlled will be opened when all of the Silver Rupees that used to be in that room have been " + "found wherever they have been shuffled to."; + mOptionDescriptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH] = + "Adds a special item to the pool that causes all " + "Silver Rupee puzzles to be completed regardless of how many Silver Rupees you have collected."; } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index cac735121ef..a88b8907c67 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3395,6 +3395,70 @@ std::map rcToRandomizerInf = { { RC_ZR_TREE, RAND_INF_ZR_TREE }, { RC_KAK_TREE, RAND_INF_KAK_TREE }, { RC_LLR_TREE, RAND_INF_LLR_TREE }, + { RC_HF_BUSH_NEAR_LAKE_1, RAND_INF_HF_BUSH_NEAR_LAKE_1 }, + { RC_HF_BUSH_NEAR_LAKE_2, RAND_INF_HF_BUSH_NEAR_LAKE_2 }, + { RC_HF_BUSH_NEAR_LAKE_3, RAND_INF_HF_BUSH_NEAR_LAKE_3 }, + { RC_HF_BUSH_NEAR_LAKE_4, RAND_INF_HF_BUSH_NEAR_LAKE_4 }, + { RC_HF_BUSH_NEAR_LAKE_5, RAND_INF_HF_BUSH_NEAR_LAKE_5 }, + { RC_HF_BUSH_NEAR_LAKE_6, RAND_INF_HF_BUSH_NEAR_LAKE_6 }, + { RC_HF_BUSH_NEAR_LAKE_7, RAND_INF_HF_BUSH_NEAR_LAKE_7 }, + { RC_HF_BUSH_NEAR_LAKE_8, RAND_INF_HF_BUSH_NEAR_LAKE_8 }, + { RC_HF_BUSH_NEAR_LAKE_9, RAND_INF_HF_BUSH_NEAR_LAKE_9 }, + { RC_HF_BUSH_NEAR_LAKE_10, RAND_INF_HF_BUSH_NEAR_LAKE_10 }, + { RC_HF_BUSH_NEAR_LAKE_11, RAND_INF_HF_BUSH_NEAR_LAKE_11 }, + { RC_HF_NORTHERN_BUSH_1, RAND_INF_HF_NORTHERN_BUSH_1 }, + { RC_HF_NORTHERN_BUSH_2, RAND_INF_HF_NORTHERN_BUSH_2 }, + { RC_HF_NORTHERN_BUSH_3, RAND_INF_HF_NORTHERN_BUSH_3 }, + { RC_HF_NORTHERN_BUSH_4, RAND_INF_HF_NORTHERN_BUSH_4 }, + { RC_HF_NORTHERN_BUSH_5, RAND_INF_HF_NORTHERN_BUSH_5 }, + { RC_HF_NORTHERN_BUSH_6, RAND_INF_HF_NORTHERN_BUSH_6 }, + { RC_HF_CHILD_NORTHERN_BUSH_1, RAND_INF_HF_CHILD_NORTHERN_BUSH_1 }, + { RC_HF_CHILD_NORTHERN_BUSH_2, RAND_INF_HF_CHILD_NORTHERN_BUSH_2 }, + { RC_HF_CHILD_NORTHERN_BUSH_3, RAND_INF_HF_CHILD_NORTHERN_BUSH_3 }, + { RC_HF_CHILD_NORTHERN_BUSH_4, RAND_INF_HF_CHILD_NORTHERN_BUSH_4 }, + { RC_HF_CHILD_NORTHERN_BUSH_5, RAND_INF_HF_CHILD_NORTHERN_BUSH_5 }, + { RC_HF_CHILD_NORTHERN_BUSH_6, RAND_INF_HF_CHILD_NORTHERN_BUSH_6 }, + { RC_HF_CHILD_NORTHERN_BUSH_7, RAND_INF_HF_CHILD_NORTHERN_BUSH_7 }, + { RC_HF_CHILD_NORTHERN_BUSH_8, RAND_INF_HF_CHILD_NORTHERN_BUSH_8 }, + { RC_HF_CHILD_NORTHERN_BUSH_9, RAND_INF_HF_CHILD_NORTHERN_BUSH_9 }, + { RC_HF_CHILD_NORTHERN_BUSH_10, RAND_INF_HF_CHILD_NORTHERN_BUSH_10 }, + { RC_HF_CHILD_NORTHERN_BUSH_11, RAND_INF_HF_CHILD_NORTHERN_BUSH_11 }, + { RC_HF_BUSH_BY_ROCKY_PATH_1, RAND_INF_HF_BUSH_BY_ROCKY_PATH_1 }, + { RC_HF_BUSH_BY_ROCKY_PATH_2, RAND_INF_HF_BUSH_BY_ROCKY_PATH_2 }, + { RC_HF_BUSH_BY_ROCKY_PATH_3, RAND_INF_HF_BUSH_BY_ROCKY_PATH_3 }, + { RC_HF_BUSH_BY_ROCKY_PATH_4, RAND_INF_HF_BUSH_BY_ROCKY_PATH_4 }, + { RC_HF_BUSH_BY_ROCKY_PATH_5, RAND_INF_HF_BUSH_BY_ROCKY_PATH_5 }, + { RC_HF_BUSH_BY_ROCKY_PATH_6, RAND_INF_HF_BUSH_BY_ROCKY_PATH_6 }, + { RC_HF_SOUTHERN_BUSH_1, RAND_INF_HF_SOUTHERN_BUSH_1 }, + { RC_HF_SOUTHERN_BUSH_2, RAND_INF_HF_SOUTHERN_BUSH_2 }, + { RC_HF_SOUTHERN_BUSH_3, RAND_INF_HF_SOUTHERN_BUSH_3 }, + { RC_HF_SOUTHERN_BUSH_4, RAND_INF_HF_SOUTHERN_BUSH_4 }, + { RC_HF_SOUTHERN_BUSH_5, RAND_INF_HF_SOUTHERN_BUSH_5 }, + { RC_HF_SOUTHERN_BUSH_6, RAND_INF_HF_SOUTHERN_BUSH_6 }, + { RC_HF_SOUTHERN_BUSH_7, RAND_INF_HF_SOUTHERN_BUSH_7 }, + { RC_HF_SOUTHERN_BUSH_8, RAND_INF_HF_SOUTHERN_BUSH_8 }, + { RC_HF_SOUTHERN_BUSH_9, RAND_INF_HF_SOUTHERN_BUSH_9 }, + { RC_HF_SOUTHERN_BUSH_10, RAND_INF_HF_SOUTHERN_BUSH_10 }, + { RC_HF_SOUTHERN_BUSH_11, RAND_INF_HF_SOUTHERN_BUSH_11 }, + { RC_HF_SOUTHERN_BUSH_12, RAND_INF_HF_SOUTHERN_BUSH_12 }, + { RC_HF_CHILD_SOUTHERN_BUSH_1, RAND_INF_HF_CHILD_SOUTHERN_BUSH_1 }, + { RC_HF_CHILD_SOUTHERN_BUSH_2, RAND_INF_HF_CHILD_SOUTHERN_BUSH_2 }, + { RC_HF_CHILD_SOUTHERN_BUSH_3, RAND_INF_HF_CHILD_SOUTHERN_BUSH_3 }, + { RC_HF_CHILD_SOUTHERN_BUSH_4, RAND_INF_HF_CHILD_SOUTHERN_BUSH_4 }, + { RC_HF_CHILD_SOUTHERN_BUSH_5, RAND_INF_HF_CHILD_SOUTHERN_BUSH_5 }, + { RC_HF_CHILD_SOUTHERN_BUSH_6, RAND_INF_HF_CHILD_SOUTHERN_BUSH_6 }, + { RC_HF_CHILD_SOUTHERN_BUSH_7, RAND_INF_HF_CHILD_SOUTHERN_BUSH_7 }, + { RC_HF_CHILD_SOUTHERN_BUSH_8, RAND_INF_HF_CHILD_SOUTHERN_BUSH_8 }, + { RC_HF_CHILD_SOUTHERN_BUSH_9, RAND_INF_HF_CHILD_SOUTHERN_BUSH_9 }, + { RC_HF_CHILD_SOUTHERN_BUSH_10, RAND_INF_HF_CHILD_SOUTHERN_BUSH_10 }, + { RC_HF_CHILD_SOUTHERN_BUSH_11, RAND_INF_HF_CHILD_SOUTHERN_BUSH_11 }, + { RC_HF_CHILD_SOUTHERN_BUSH_12, RAND_INF_HF_CHILD_SOUTHERN_BUSH_12 }, + { RC_ZF_BUSH_1, RAND_INF_ZF_BUSH_1 }, + { RC_ZF_BUSH_2, RAND_INF_ZF_BUSH_2 }, + { RC_ZF_BUSH_3, RAND_INF_ZF_BUSH_3 }, + { RC_ZF_BUSH_4, RAND_INF_ZF_BUSH_4 }, + { RC_ZF_BUSH_5, RAND_INF_ZF_BUSH_5 }, + { RC_ZF_BUSH_6, RAND_INF_ZF_BUSH_6 }, }; BeehiveIdentity Randomizer::IdentifyBeehive(s32 sceneNum, s16 xPosition, s32 respawnData) { @@ -4769,6 +4833,15 @@ template void CreateGetItemMessages(const std::arrayCreateMessage( + Randomizer::getItemMessageTableID, RG_SILVER_RUPEE_FIRST, + CustomMessage("You got a %c[[rupee_name]]%w! [[count_text]]", TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM)); + + customMessageManager->CreateMessage( + Randomizer::getItemMessageTableID, RG_BOTTOMLESS_SILVER_RUPEE_POUCH, + CustomMessage("You found the %cBottomless Silver Rupee Pouch! All Silver Rupee Puzzles are Unlocked", + TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM)); } void CreateRupeeMessages() { @@ -5488,7 +5561,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = { { + const std::array getItemMessages = { { GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn&wirklich gefunden!", "Félicitation! Vous avez trouvé %gGreg%w!"), GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", @@ -5764,6 +5837,27 @@ void Randomizer::CreateCustomMessages() { "Du erhältst die %rKindergeldbörse%w!&Jetzt kannst Du bis&zu %y99 Rubine%w mit Dir führen!", "Vous obtenez la %rPetite Bourse%w!&Elle peut contenir jusqu'à %y99 rubis%w!"), + GIMESSAGE(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, ITEM_BEAN, "You found the&%gDeath Mountain Crater Bean Soul%w!", + TODO_TRANSLATE, TODO_TRANSLATE), + GIMESSAGE(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, ITEM_BEAN, "You found the&%gDeath Mountain Trail Bean Soul%w!", + TODO_TRANSLATE, TODO_TRANSLATE), + GIMESSAGE(RG_DESERT_COLOSSUS_BEAN_SOUL, ITEM_BEAN, "You found the&%gDesert Colossus Bean Soul%w!", + TODO_TRANSLATE, TODO_TRANSLATE), + GIMESSAGE(RG_GERUDO_VALLEY_BEAN_SOUL, ITEM_BEAN, "You found the&%gGerudo Valley Bean Soul%w!", TODO_TRANSLATE, + TODO_TRANSLATE), + GIMESSAGE(RG_GRAVEYARD_BEAN_SOUL, ITEM_BEAN, "You found the&%gGraveyard Bean Soul%w!", TODO_TRANSLATE, + TODO_TRANSLATE), + GIMESSAGE(RG_KOKIRI_FOREST_BEAN_SOUL, ITEM_BEAN, "You found the&%gKokiri Forest Bean Soul%w!", TODO_TRANSLATE, + TODO_TRANSLATE), + GIMESSAGE(RG_LAKE_HYLIA_BEAN_SOUL, ITEM_BEAN, "You found the&%gLake Hylia Bean Soul%w!", TODO_TRANSLATE, + TODO_TRANSLATE), + GIMESSAGE(RG_LOST_WOODS_BRIDGE_BEAN_SOUL, ITEM_BEAN, "You found the&%gLost Wood's Bridge Bean Soul%w!", + TODO_TRANSLATE, TODO_TRANSLATE), + GIMESSAGE(RG_LOST_WOODS_BEAN_SOUL, ITEM_BEAN, "You found the&%gLost Wood's Theatre Bean Soul%w!", + TODO_TRANSLATE, TODO_TRANSLATE), + GIMESSAGE(RG_ZORAS_RIVER_BEAN_SOUL, ITEM_BEAN, "You found the&%gZora's River Bean Soul%w!", TODO_TRANSLATE, + TODO_TRANSLATE), + GIMESSAGE(RG_GOHMA_SOUL, ITEM_BIG_POE, "You found the soul for %gGohma%w!", "Du hast die Seele von&%gGohma%w gefunden!", "Vous obtenez l'âme de %gGohma%w!"), GIMESSAGE(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, "You found the soul for %rKing&Dodongo%w!", @@ -5812,6 +5906,8 @@ void Randomizer::CreateCustomMessages() { GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", "Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!", "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), + GIMESSAGE(RG_OPEN_CHEST, ITEM_KEY_SMALL, "You got the %rAbility to Open Chests%w!", TODO_TRANSLATE, + TODO_TRANSLATE), GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!", "Du hast eine verlorene %rAngelrute%w&gefunden!&Zeit, im Teich&zu angeln!", "Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"), @@ -5982,6 +6078,7 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem); std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, + { RG_OPEN_CHEST, RAND_INF_CAN_OPEN_CHEST }, { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, { RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG }, @@ -5996,6 +6093,16 @@ std::map randomizerGetToRandInf = { { RG_OCARINA_C_DOWN_BUTTON, RAND_INF_HAS_OCARINA_C_DOWN }, { RG_OCARINA_C_LEFT_BUTTON, RAND_INF_HAS_OCARINA_C_LEFT }, { RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT }, + { RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL }, + { RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL }, + { RG_DESERT_COLOSSUS_BEAN_SOUL, RAND_INF_DESERT_COLOSSUS_BEAN_SOUL }, + { RG_GERUDO_VALLEY_BEAN_SOUL, RAND_INF_GERUDO_VALLEY_BEAN_SOUL }, + { RG_GRAVEYARD_BEAN_SOUL, RAND_INF_GRAVEYARD_BEAN_SOUL }, + { RG_KOKIRI_FOREST_BEAN_SOUL, RAND_INF_KOKIRI_FOREST_BEAN_SOUL }, + { RG_LAKE_HYLIA_BEAN_SOUL, RAND_INF_LAKE_HYLIA_BEAN_SOUL }, + { RG_LOST_WOODS_BRIDGE_BEAN_SOUL, RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL }, + { RG_LOST_WOODS_BEAN_SOUL, RAND_INF_LOST_WOODS_BEAN_SOUL }, + { RG_ZORAS_RIVER_BEAN_SOUL, RAND_INF_ZORAS_RIVER_BEAN_SOUL }, { RG_GOHMA_SOUL, RAND_INF_GOHMA_SOUL }, { RG_KING_DODONGO_SOUL, RAND_INF_KING_DODONGO_SOUL }, { RG_BARINADE_SOUL, RAND_INF_BARINADE_SOUL }, @@ -6195,6 +6302,18 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { Flags_SetRandomizerInf( (RandomizerInf)((int)RAND_INF_GUARD_HOUSE_UNLOCKED + ((item - RG_GUARD_HOUSE_KEY) * 2) + 1)); return Return_Item_Entry(giEntry, RG_NONE); + } else if (item >= RG_SILVER_RUPEE_FIRST && item <= RG_SILVER_RUPEE_LAST) { + OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(static_cast(item)) + .IncrementCollected(); + return Return_Item_Entry(giEntry, RG_NONE); + } else if (item == RG_BOTTOMLESS_SILVER_RUPEE_POUCH) { + for (int i = RG_SILVER_RUPEE_FIRST; i <= RG_SILVER_RUPEE_LAST; i++) { + int max = + OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(static_cast(i)).GetTotal(); + OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(static_cast(i)) + .IncrementCollected(max); + } + return Return_Item_Entry(giEntry, RG_NONE); } switch (item) { @@ -6216,6 +6335,18 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) { INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; AMMO(ITEM_BEAN) = 10; + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_PLANTING_BEANS)) { + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6); + gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24); + gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9); + gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1); + gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18); + gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3); + AMMO(ITEM_BEAN) = 0; + } } break; case RG_DOUBLE_DEFENSE: diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 63706ef203a..a989836928d 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -418,6 +418,7 @@ typedef enum { RCTYPE_SMALL_CRATE, // Small crates RCTYPE_TREE, // Trees RCTYPE_NLTREE, // NL Trees + RCTYPE_BUSH, // Bushes RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) RCTYPE_OCARINA, // Ocarina locations RCTYPE_BEEHIVE, // Beehives @@ -428,6 +429,7 @@ typedef enum { RCTYPE_BEAN_FAIRY, // Fairies from Beans RCTYPE_SONG_FAIRY, // Fairies from Songs RCTYPE_GRASS, // Grass + RCTYPE_SILVER_RUPEE, // Silver Rupees } RandomizerCheckType; typedef enum { RCQUEST_VANILLA, RCQUEST_MQ, RCQUEST_BOTH } RandomizerCheckQuest; @@ -2822,6 +2824,73 @@ typedef enum { RC_LLR_TREE, // End Trees + // Start Bushes + RC_HF_BUSH_NEAR_LAKE_1, + RC_HF_BUSH_NEAR_LAKE_2, + RC_HF_BUSH_NEAR_LAKE_3, + RC_HF_BUSH_NEAR_LAKE_4, + RC_HF_BUSH_NEAR_LAKE_5, + RC_HF_BUSH_NEAR_LAKE_6, + RC_HF_BUSH_NEAR_LAKE_7, + RC_HF_BUSH_NEAR_LAKE_8, + RC_HF_BUSH_NEAR_LAKE_9, + RC_HF_BUSH_NEAR_LAKE_10, + RC_HF_BUSH_NEAR_LAKE_11, + RC_HF_NORTHERN_BUSH_1, + RC_HF_NORTHERN_BUSH_2, + RC_HF_NORTHERN_BUSH_3, + RC_HF_NORTHERN_BUSH_4, + RC_HF_NORTHERN_BUSH_5, + RC_HF_NORTHERN_BUSH_6, + RC_HF_CHILD_NORTHERN_BUSH_1, + RC_HF_CHILD_NORTHERN_BUSH_2, + RC_HF_CHILD_NORTHERN_BUSH_3, + RC_HF_CHILD_NORTHERN_BUSH_4, + RC_HF_CHILD_NORTHERN_BUSH_5, + RC_HF_CHILD_NORTHERN_BUSH_6, + RC_HF_CHILD_NORTHERN_BUSH_7, + RC_HF_CHILD_NORTHERN_BUSH_8, + RC_HF_CHILD_NORTHERN_BUSH_9, + RC_HF_CHILD_NORTHERN_BUSH_10, + RC_HF_CHILD_NORTHERN_BUSH_11, + RC_HF_BUSH_BY_ROCKY_PATH_1, + RC_HF_BUSH_BY_ROCKY_PATH_2, + RC_HF_BUSH_BY_ROCKY_PATH_3, + RC_HF_BUSH_BY_ROCKY_PATH_4, + RC_HF_BUSH_BY_ROCKY_PATH_5, + RC_HF_BUSH_BY_ROCKY_PATH_6, + RC_HF_SOUTHERN_BUSH_1, + RC_HF_SOUTHERN_BUSH_2, + RC_HF_SOUTHERN_BUSH_3, + RC_HF_SOUTHERN_BUSH_4, + RC_HF_SOUTHERN_BUSH_5, + RC_HF_SOUTHERN_BUSH_6, + RC_HF_SOUTHERN_BUSH_7, + RC_HF_SOUTHERN_BUSH_8, + RC_HF_SOUTHERN_BUSH_9, + RC_HF_SOUTHERN_BUSH_10, + RC_HF_SOUTHERN_BUSH_11, + RC_HF_SOUTHERN_BUSH_12, + RC_HF_CHILD_SOUTHERN_BUSH_1, + RC_HF_CHILD_SOUTHERN_BUSH_2, + RC_HF_CHILD_SOUTHERN_BUSH_3, + RC_HF_CHILD_SOUTHERN_BUSH_4, + RC_HF_CHILD_SOUTHERN_BUSH_5, + RC_HF_CHILD_SOUTHERN_BUSH_6, + RC_HF_CHILD_SOUTHERN_BUSH_7, + RC_HF_CHILD_SOUTHERN_BUSH_8, + RC_HF_CHILD_SOUTHERN_BUSH_9, + RC_HF_CHILD_SOUTHERN_BUSH_10, + RC_HF_CHILD_SOUTHERN_BUSH_11, + RC_HF_CHILD_SOUTHERN_BUSH_12, + RC_ZF_BUSH_1, + RC_ZF_BUSH_2, + RC_ZF_BUSH_3, + RC_ZF_BUSH_4, + RC_ZF_BUSH_5, + RC_ZF_BUSH_6, + // End Bushes + RC_PIERRE, RC_DELIVER_RUTOS_LETTER, RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, @@ -3688,6 +3757,159 @@ typedef enum { RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8, // End Grass + // Vanilla Silver Rupee Locations + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1, + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2, + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3, + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4, + RC_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5, + RC_SHADOW_SCYTHE_SILVER_RUPEE_1, + RC_SHADOW_SCYTHE_SILVER_RUPEE_2, + RC_SHADOW_SCYTHE_SILVER_RUPEE_3, + RC_SHADOW_SCYTHE_SILVER_RUPEE_4, + RC_SHADOW_SCYTHE_SILVER_RUPEE_5, + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, + RC_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1, + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2, + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3, + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4, + RC_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5, + RC_SPIRIT_GATE_SILVER_RUPEE_1, + RC_SPIRIT_GATE_SILVER_RUPEE_2, + RC_SPIRIT_GATE_SILVER_RUPEE_3, + RC_SPIRIT_GATE_SILVER_RUPEE_4, + RC_SPIRIT_GATE_SILVER_RUPEE_5, + RC_SPIRIT_BEAMOS_SILVER_RUPEE_1, + RC_SPIRIT_BEAMOS_SILVER_RUPEE_2, + RC_SPIRIT_BEAMOS_SILVER_RUPEE_3, + RC_SPIRIT_BEAMOS_SILVER_RUPEE_4, + RC_SPIRIT_BEAMOS_SILVER_RUPEE_5, + RC_SPIRIT_BOULDER_SILVER_RUPEE_1, + RC_SPIRIT_BOULDER_SILVER_RUPEE_2, + RC_SPIRIT_BOULDER_SILVER_RUPEE_3, + RC_SPIRIT_BOULDER_SILVER_RUPEE_4, + RC_SPIRIT_BOULDER_SILVER_RUPEE_5, + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1, + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2, + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3, + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4, + RC_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5, + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_1, + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_2, + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_3, + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_4, + RC_ICE_CAVERN_SLIDING_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3, + RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4, + RC_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3, + RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4, + RC_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3, + RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4, + RC_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5, + RC_FOREST_TRIAL_SILVER_RUPEE_1, + RC_FOREST_TRIAL_SILVER_RUPEE_2, + RC_FOREST_TRIAL_SILVER_RUPEE_3, + RC_FOREST_TRIAL_SILVER_RUPEE_4, + RC_FOREST_TRIAL_SILVER_RUPEE_5, + RC_FIRE_TRIAL_SILVER_RUPEE_1, + RC_FIRE_TRIAL_SILVER_RUPEE_2, + RC_FIRE_TRIAL_SILVER_RUPEE_3, + RC_FIRE_TRIAL_SILVER_RUPEE_4, + RC_FIRE_TRIAL_SILVER_RUPEE_5, + RC_LIGHT_TRIAL_SILVER_RUPEE_1, + RC_LIGHT_TRIAL_SILVER_RUPEE_2, + RC_LIGHT_TRIAL_SILVER_RUPEE_3, + RC_LIGHT_TRIAL_SILVER_RUPEE_4, + RC_LIGHT_TRIAL_SILVER_RUPEE_5, + RC_SPIRIT_TRIAL_SILVER_RUPEE_1, + RC_SPIRIT_TRIAL_SILVER_RUPEE_2, + RC_SPIRIT_TRIAL_SILVER_RUPEE_3, + RC_SPIRIT_TRIAL_SILVER_RUPEE_4, + RC_SPIRIT_TRIAL_SILVER_RUPEE_5, + // MQ Silver Rupee Locations + RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1, + RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2, + RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3, + RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4, + RC_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5, + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1, + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2, + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3, + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4, + RC_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9, + RC_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10, + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1, + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2, + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3, + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4, + RC_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9, + RC_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10, + RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1, + RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2, + RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3, + RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4, + RC_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_3, + RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_4, + RC_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_3, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_4, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_5, + RC_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_6, + RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_1, + RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_2, + RC_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_3, + RC_FIRE_TRIAL_MQ_SILVER_RUPEE_1, + RC_FIRE_TRIAL_MQ_SILVER_RUPEE_2, + RC_FIRE_TRIAL_MQ_SILVER_RUPEE_3, + RC_FIRE_TRIAL_MQ_SILVER_RUPEE_4, + RC_FIRE_TRIAL_MQ_SILVER_RUPEE_5, + RC_WATER_TRIAL_MQ_SILVER_RUPEE_1, + RC_WATER_TRIAL_MQ_SILVER_RUPEE_2, + RC_WATER_TRIAL_MQ_SILVER_RUPEE_3, + RC_WATER_TRIAL_MQ_SILVER_RUPEE_4, + RC_WATER_TRIAL_MQ_SILVER_RUPEE_5, + RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_1, + RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_2, + RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_3, + RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_4, + RC_SHADOW_TRIAL_MQ_SILVER_RUPEE_5, + // End Silver Rupees + RC_MAX } RandomizerCheck; @@ -4163,6 +4385,16 @@ typedef enum { RG_BUY_RED_POTION_50, RG_TRIFORCE, RG_TRIFORCE_PIECE, + RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, + RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, + RG_DESERT_COLOSSUS_BEAN_SOUL, + RG_GERUDO_VALLEY_BEAN_SOUL, + RG_GRAVEYARD_BEAN_SOUL, + RG_KOKIRI_FOREST_BEAN_SOUL, + RG_LAKE_HYLIA_BEAN_SOUL, + RG_LOST_WOODS_BRIDGE_BEAN_SOUL, + RG_LOST_WOODS_BEAN_SOUL, + RG_ZORAS_RIVER_BEAN_SOUL, RG_GOHMA_SOUL, RG_KING_DODONGO_SOUL, RG_BARINADE_SOUL, @@ -4181,9 +4413,41 @@ typedef enum { RG_FISHING_POLE, RG_DEKU_STICK_BAG, RG_DEKU_NUT_BAG, + RG_SILVER_RUPEE_FIRST, + RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE = RG_SILVER_RUPEE_FIRST, // for convenience + RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, + RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, + RG_SPIRIT_GATE_SILVER_RUPEE, + RG_SPIRIT_BEAMOS_SILVER_RUPEE, + RG_SPIRIT_BOULDER_SILVER_RUPEE, + RG_SHADOW_SCYTHE_SILVER_RUPEE, + RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + RG_FOREST_TRIAL_SILVER_RUPEE, + RG_FIRE_TRIAL_SILVER_RUPEE, + RG_SPIRIT_TRIAL_SILVER_RUPEE, + RG_LIGHT_TRIAL_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, + RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, + RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, + RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, + RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, + RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, + RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, + RG_FIRE_TRIAL_MQ_SILVER_RUPEE, + RG_WATER_TRIAL_MQ_SILVER_RUPEE, + RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + RG_SILVER_RUPEE_LAST = RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, + RG_BOTTOMLESS_SILVER_RUPEE_POUCH, RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, + RG_OPEN_CHEST, RG_CHILD_WALLET, RG_BOMBCHU_BAG, RG_QUIVER_INF, @@ -5135,6 +5399,28 @@ typedef enum { RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RHT_BEEHIVE_BEHIND_KING_ZORA, + // Silver Rupee Locations + RHT_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, + RHT_ICE_CAVERN_SLIDING_SILVER_RUPEE, + RHT_BOTTOM_OF_THE_WELL_BASEMENT_SILVER_RUPEE, + RHT_GERUDO_TRAINING_GROUND_BOULDER_SILVER_RUPEE, + RHT_GERUDO_TRAINING_GROUND_LAVA_SILVER_RUPEE, + RHT_GERUDO_TRAINING_GROUND_TOILET_SILVER_RUPEE, + RHT_SPIRIT_GATE_SILVER_RUPEE, + RHT_SPIRIT_BEAMOS_SILVER_RUPEE, + RHT_SPIRIT_BOULDER_SILVER_RUPEE, + RHT_SPIRIT_LOBBY_SILVER_RUPEE, + RHT_SHADOW_SPINNING_SCYTHE_SILVER_RUPEE, + RHT_SHADOW_INVISIBLE_SCYTHE_SILVER_RUPEE, + RHT_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, + RHT_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, + RHT_FOREST_TRIAL_SILVER_RUPEE, + RHT_FIRE_TRIAL_SILVER_RUPEE, + RHT_SPIRIT_TRIAL_SILVER_RUPEE, + RHT_LIGHT_TRIAL_SILVER_RUPEE, + RHT_DODONGOS_CAVERN_SILVER_RUPEE, + RHT_WATER_TRIAL_SILVER_RUPEE, + RHT_SHADOW_TRIAL_SILVER_RUPEE, // Items RHT_KOKIRI_SWORD, RHT_MASTER_SWORD, @@ -5366,6 +5652,7 @@ typedef enum { RHT_DEKU_STICK_CAPACITY_20, RHT_DEKU_STICK_CAPACITY_30, RHT_TRIFORCE_PIECE, + RHT_BEAN_SOUL, RHT_GOHMA_SOUL, RHT_KING_DODONGO_SOUL, RHT_BARINADE_SOUL, @@ -5381,8 +5668,18 @@ typedef enum { RHT_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RHT_BRONZE_SCALE, + RHT_OPEN_CHEST, RHT_FISHING_POLE, RHT_SKELETON_KEY, + // Silver Rupee Items + RHT_DC_SILVER_RUPEE, + RHT_ICE_CAVERN_SILVER_RUPEE, + RHT_BOTTOM_OF_THE_WELL_SILVER_RUPEE, + RHT_GERUDO_TRAINING_GROUND_SILVER_RUPEE, + RHT_SPIRIT_TEMPLE_SILVER_RUPEE, + RHT_SHADOW_TEMPLE_SILVER_RUPEE, + RHT_GANONS_CASTLE_SILVER_RUPEE, + RHT_BOTTOMLESS_SILVER_RUPEE_POUCH, RHT_EPONA, RHT_OVERWORLD_KEY, RHT_HINT_MYSTERIOUS, @@ -5670,6 +5967,8 @@ typedef enum { RHT_TREE_ZORAS_RIVER, RHT_TREE_LON_LON_RANCH, RHT_TREE_KAKARIKO, + RHT_BUSH_HYRULE_FIELD, + RHT_BUSH_ZORAS_FOUNTAIN, // Ganon Line RHT_GANON_JOKE01, RHT_GANON_JOKE02, @@ -5958,6 +6257,7 @@ typedef enum { RSK_SHUFFLE_OCARINA, RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, + RSK_SHUFFLE_OPEN_CHEST, RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, RSK_STARTING_MASTER_SWORD, @@ -6010,6 +6310,7 @@ typedef enum { RSK_SHUFFLE_POTS, RSK_SHUFFLE_CRATES, RSK_SHUFFLE_TREES, + RSK_SHUFFLE_BUSHES, RSK_SHUFFLE_FROG_SONG_RUPEES, RSK_ITEM_POOL, RSK_ICE_TRAPS, @@ -6057,6 +6358,7 @@ typedef enum { RSK_SKIP_EPONA_RACE, RSK_COMPLETE_MASK_QUEST, RSK_SKIP_SCARECROWS_SONG, + RSK_SKIP_PLANTING_BEANS, RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, RSK_SHUFFLE_MERCHANTS, @@ -6134,6 +6436,7 @@ typedef enum { RSK_TRIFORCE_HUNT, RSK_TRIFORCE_HUNT_PIECES_TOTAL, RSK_TRIFORCE_HUNT_PIECES_REQUIRED, + RSK_SHUFFLE_BEAN_SOULS, RSK_SHUFFLE_BOSS_SOULS, RSK_FISHSANITY, RSK_FISHSANITY_POND_COUNT, @@ -6150,6 +6453,8 @@ typedef enum { RSK_SHUFFLE_SONG_FAIRIES, RSK_LOCK_OVERWORLD_DOORS, RSK_SHUFFLE_GRASS, + RSK_SHUFFLE_SILVER_RUPEES, + RSK_BOTTOMLESS_SILVER_RUPEE_POUCH, RSK_MAX } RandomizerSettingKey; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 022303aa321..4e8d0fbe65a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -83,6 +83,7 @@ bool showDungeonGrass; bool showOverworldCrates; bool showDungeonCrates; bool showTrees; +bool showBushes; bool showFrogSongRupees; bool showFountainFairies; bool showStoneFairies; @@ -1485,6 +1486,7 @@ void LoadSettings() { break; } showTrees = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TREES); + showBushes = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BUSHES); } else { // Vanilla showOverworldTokens = true; showDungeonTokens = true; @@ -1495,6 +1497,7 @@ void LoadSettings() { showOverworldCrates = false; showDungeonCrates = false; showTrees = false; + showBushes = false; } fortressFast = false; @@ -1611,7 +1614,7 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_NLTREE || (showTrees && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) == RO_LOGIC_NO_LOGIC)) && - (loc->GetRCType() != RCTYPE_COW || showCows) && + (loc->GetRCType() != RCTYPE_BUSH || showBushes) && (loc->GetRCType() != RCTYPE_COW || showCows) && (loc->GetRCType() != RCTYPE_FISH || OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) && (loc->GetRCType() != RCTYPE_FREESTANDING || diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8742805a6f2..4fcd2518444 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -182,6 +182,17 @@ DEFINE_RAND_INF(RAND_INF_ADULT_LOACH) DEFINE_RAND_INF(RAND_INF_10_BIG_POES) DEFINE_RAND_INF(RAND_INF_GRANT_GANONS_BOSSKEY) +DEFINE_RAND_INF(RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_DESERT_COLOSSUS_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_GERUDO_VALLEY_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_GRAVEYARD_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_KOKIRI_FOREST_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_LAKE_HYLIA_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_LOST_WOODS_BEAN_SOUL) +DEFINE_RAND_INF(RAND_INF_ZORAS_RIVER_BEAN_SOUL) + DEFINE_RAND_INF(RAND_INF_GOHMA_SOUL) DEFINE_RAND_INF(RAND_INF_KING_DODONGO_SOUL) DEFINE_RAND_INF(RAND_INF_BARINADE_SOUL) @@ -1060,10 +1071,75 @@ DEFINE_RAND_INF(RAND_INF_ZF_TREE) DEFINE_RAND_INF(RAND_INF_ZR_TREE) DEFINE_RAND_INF(RAND_INF_KAK_TREE) DEFINE_RAND_INF(RAND_INF_LLR_TREE) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_1) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_2) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_3) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_4) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_5) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_6) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_7) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_8) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_9) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_10) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_11) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_1) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_2) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_3) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_4) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_5) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_12) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_12) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_1) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_2) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_3) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_4) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_5) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_6) DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) DEFINE_RAND_INF(RAND_INF_CAN_SWIM) +DEFINE_RAND_INF(RAND_INF_CAN_OPEN_CHEST) DEFINE_RAND_INF(RAND_INF_HAS_WALLET) @@ -2016,4 +2092,156 @@ DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_6) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_7) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_8) // End Grass -DEFINE_RAND_INF(RAND_INF_OBTAINED_RUTOS_LETTER) \ No newline at end of file +DEFINE_RAND_INF(RAND_INF_OBTAINED_RUTOS_LETTER) +// Silver Rupee +DEFINE_RAND_INF(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_BOTTOM_OF_THE_WELL_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_ICE_CAVERN_SLIDING_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE_6) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SPIRIT_GATE_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BEAMOS_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BOULDER_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_SCYTHE_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_FOREST_TRIAL_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_LIGHT_TRIAL_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TRIAL_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE_6) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_SCYTHE_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_6) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_7) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_8) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_9) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE_10) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_6) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_7) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_8) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_9) +DEFINE_RAND_INF(RAND_INF_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE_10) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_FIRE_TRIAL_MQ_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_WATER_TRIAL_MQ_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_1) +DEFINE_RAND_INF(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_2) +DEFINE_RAND_INF(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_3) +DEFINE_RAND_INF(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_4) +DEFINE_RAND_INF(RAND_INF_SHADOW_TRIAL_MQ_SILVER_RUPEE_5) +DEFINE_RAND_INF(RAND_INF_MAGICAL_SILVER_RUPEE) \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 0935ce46c06..f9a61eee8af 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,6 +9,7 @@ #include "randomizer_check_tracker.h" #include "randomizer_item_tracker.h" #include "randomizerTypes.h" +#include "dungeon.h" #include "soh/cvar_prefixes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/OTRGlobals.h" @@ -28,6 +29,7 @@ extern PlayState* gPlayState; #include "textures/icon_item_static/icon_item_static.h" #include "textures/icon_item_24_static/icon_item_24_static.h" +#include } void DrawEquip(ItemTrackerItem item); @@ -55,12 +57,14 @@ static WidgetInfo triforcePieceCount; static WidgetInfo dungeonItemTracking; static WidgetInfo gregTracking; static WidgetInfo triforcePieceTracking; +static WidgetInfo beanSoulsTracking; static WidgetInfo bossSoulsTracking; static WidgetInfo ocarinaButtonTracking; static WidgetInfo overworldKeysTracking; static WidgetInfo fishingPoleTracking; static WidgetInfo personalNotesWiget; static WidgetInfo hookshotIdentWidget; +static WidgetInfo silverRupeeTracking; namespace SohGui { extern std::shared_ptr mSohMenu; @@ -136,6 +140,19 @@ std::vector triforcePieces = { ITEM_TRACKER_ITEM(RG_TRIFORCE_PIECE, 0, DrawItem), }; +std::vector beanSoulItems = { + ITEM_TRACKER_ITEM_CUSTOM(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_DESERT_COLOSSUS_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_VALLEY_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GRAVEYARD_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_KOKIRI_FOREST_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_LAKE_HYLIA_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_LOST_WOODS_BRIDGE_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_LOST_WOODS_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_ZORAS_RIVER_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), +}; + std::vector bossSoulItems = { ITEM_TRACKER_ITEM(RG_GOHMA_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_KING_DODONGO_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_BARINADE_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_PHANTOM_GANON_SOUL, 0, DrawItem), @@ -183,6 +200,49 @@ std::vector overworldKeyItems = { ITEM_TRACKER_ITEM_CUSTOM(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), }; +std::vector silverRupeeItems = { + ITEM_TRACKER_ITEM_CUSTOM(RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_ICE_CAVERN_SLIDING_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SPIRIT_GATE_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SPIRIT_BEAMOS_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SPIRIT_BOULDER_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_SCYTHE_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_FOREST_TRIAL_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_FIRE_TRIAL_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SPIRIT_TRIAL_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_LIGHT_TRIAL_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, + 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, + DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_FIRE_TRIAL_MQ_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_WATER_TRIAL_MQ_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_ITEM_CUSTOM(RG_SHADOW_TRIAL_MQ_SILVER_RUPEE, ITEM_RUPEE_SILVER, ITEM_RUPEE_SILVER, 0, DrawItem), +}; + std::vector fishingPoleItems = { ITEM_TRACKER_ITEM(ITEM_FISHING_POLE, 0, DrawItem) }; std::vector itemTrackerDungeonsWithMapsHorizontal = { @@ -246,6 +306,19 @@ std::map itemTrackerDungeonShortNames = { { SCENE_THIEVES_HIDEOUT, "HIDE" }, }; +std::map itemTrackerBeanShortNames = { + { RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, "DMC" }, + { RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, "DMT" }, + { RG_DESERT_COLOSSUS_BEAN_SOUL, "DC" }, + { RG_GERUDO_VALLEY_BEAN_SOUL, "GV" }, + { RG_GRAVEYARD_BEAN_SOUL, "GY" }, + { RG_KOKIRI_FOREST_BEAN_SOUL, "KF" }, + { RG_LAKE_HYLIA_BEAN_SOUL, "LA" }, + { RG_LOST_WOODS_BRIDGE_BEAN_SOUL, "LWB" }, + { RG_LOST_WOODS_BEAN_SOUL, "LWT" }, + { RG_ZORAS_RIVER_BEAN_SOUL, "ZR" }, +}; + std::map itemTrackerBossShortNames = { { RG_GOHMA_SOUL, "GOHMA" }, { RG_KING_DODONGO_SOUL, "KD" }, { RG_BARINADE_SOUL, "BARI" }, { RG_PHANTOM_GANON_SOUL, "PG" }, { RG_VOLVAGIA_SOUL, "VOLV" }, { RG_MORPHA_SOUL, "MORPH" }, @@ -722,6 +795,30 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImGui::PushStyleColor(ImGuiCol_Text, maxColor); ImGui::Text("%s", maxString.c_str()); ImGui::PopStyleColor(); + } else if (item.id >= RG_SILVER_RUPEE_FIRST && item.id <= RG_SILVER_RUPEE_LAST && IS_RANDO && + OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Get() > + RO_DUNGEON_ITEM_LOC_VANILLA && + IsValidSaveFile()) { + RandomizerGet rgid = static_cast(item.id); + std::string current = ""; + std::string max = ""; + uint8_t rupeesMax = OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(rgid).GetTotal(); + ImU32 currentColor = OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(rgid).AllCollected() + ? IM_COL_GREEN + : IM_COL_WHITE; + ImU32 maxColor = IM_COL_GREEN; + current += std::to_string(OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(rgid).GetCollected()); + current += "/"; + max += std::to_string(rupeesMax); + ImGui::SetCursorScreenPos( + ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize((current + max).c_str()).x / 2), p.y - 14)); + ImGui::PushStyleColor(ImGuiCol_Text, currentColor); + ImGui::Text("%d/", OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(rgid).GetCollected()); + ImGui::PopStyleColor(); + ImGui::SameLine(0, 0.0f); + ImGui::PushStyleColor(ImGuiCol_Text, maxColor); + ImGui::Text("%d", rupeesMax); + ImGui::PopStyleColor(); } else { ImGui::SetCursorScreenPos(ImVec2(p.x, p.y - 14)); ImGui::Text(""); @@ -809,6 +906,56 @@ void DrawItem(ItemTrackerItem item) { hasItem = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT); itemName = "Triforce Piece"; break; + case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL); + itemName = "Death Mountain Crater Bean Soul"; + break; + case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL); + itemName = "Death Mountain Trail Bean Soul"; + break; + case RG_DESERT_COLOSSUS_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_DESERT_COLOSSUS_BEAN_SOUL); + itemName = "Desert Colossus Bean Soul"; + break; + case RG_GERUDO_VALLEY_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_GERUDO_VALLEY_BEAN_SOUL); + itemName = "Gerudo Valley Bean Soul"; + break; + case RG_GRAVEYARD_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_GRAVEYARD_BEAN_SOUL); + itemName = "Graveyard Bean Soul"; + break; + case RG_KOKIRI_FOREST_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_KOKIRI_FOREST_BEAN_SOUL); + itemName = "Kokiri Forest Bean Soul"; + break; + case RG_LAKE_HYLIA_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_LAKE_HYLIA_BEAN_SOUL); + itemName = "Lake Hylia Bean Soul"; + break; + case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL); + itemName = "Lost Woods Bridge Bean Soul"; + break; + case RG_LOST_WOODS_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_LOST_WOODS_BEAN_SOUL); + itemName = "Lost Woods Theatre Bean Soul"; + break; + case RG_ZORAS_RIVER_BEAN_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_ZORAS_RIVER_BEAN_SOUL); + itemName = "Zora's River Bean Soul"; + break; case RG_GOHMA_SOUL: actualItemId = item.id; hasItem = Flags_GetRandomizerInf(RAND_INF_GOHMA_SOUL); @@ -1009,6 +1156,41 @@ void DrawItem(ItemTrackerItem item) { hasItem = Flags_GetRandomizerInf(RAND_INF_FISHING_HOLE_KEY_OBTAINED); itemName = "Fishing Hole Key"; break; + case RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE: + case RG_ICE_CAVERN_SLIDING_SILVER_RUPEE: + case RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE: + case RG_SPIRIT_GATE_SILVER_RUPEE: + case RG_SPIRIT_BEAMOS_SILVER_RUPEE: + case RG_SPIRIT_BOULDER_SILVER_RUPEE: + case RG_SHADOW_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE: + case RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE: + case RG_FOREST_TRIAL_SILVER_RUPEE: + case RG_FIRE_TRIAL_SILVER_RUPEE: + case RG_SPIRIT_TRIAL_SILVER_RUPEE: + case RG_LIGHT_TRIAL_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE: + case RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE: + case RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE: + case RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE: + case RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE: + case RG_FIRE_TRIAL_MQ_SILVER_RUPEE: + case RG_WATER_TRIAL_MQ_SILVER_RUPEE: + case RG_SHADOW_TRIAL_MQ_SILVER_RUPEE: + actualItemId = item.id; + hasItem = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_SILVER_RUPEES).Get() > + RO_DUNGEON_ITEM_LOC_VANILLA; + itemName = Rando::StaticData::RetrieveItem(static_cast(actualItemId)) + .GetName() + .GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), LANGUAGE_ENG)); + break; } if (GameInteractor::IsSaveLoaded() && @@ -1025,6 +1207,16 @@ void DrawItem(ItemTrackerItem item) { DrawItemCount(item, false); + if (item.id >= RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL && item.id <= RG_ZORAS_RIVER_BEAN_SOUL) { + ImVec2 p = ImGui::GetCursorScreenPos(); + std::string beanName = itemTrackerBeanShortNames[item.id]; + ImGui::SetCursorScreenPos( + ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(beanName.c_str()).x / 2), p.y - (iconSize + 13))); + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); + ImGui::Text("%s", beanName.c_str()); + ImGui::PopStyleColor(); + } + if (item.id >= RG_GOHMA_SOUL && item.id <= RG_GANON_SOUL) { ImVec2 p = ImGui::GetCursorScreenPos(); std::string bossName = itemTrackerBossShortNames[item.id]; @@ -1478,6 +1670,19 @@ void UpdateVectors() { mainWindowItems.insert(mainWindowItems.end(), fishingPoleItems.begin(), fishingPoleItems.end()); } + // If we're adding bean souls to the main window... + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BeanSouls"), SECTION_DISPLAY_HIDDEN) == + SECTION_DISPLAY_MAIN_WINDOW) { + //...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce + // pieces) + while (mainWindowItems.size() % 6) { + mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); + } + + // Add bean souls + mainWindowItems.insert(mainWindowItems.end(), beanSoulItems.begin(), beanSoulItems.end()); + } + // If we're adding boss souls to the main window... if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { @@ -1517,6 +1722,26 @@ void UpdateVectors() { mainWindowItems.insert(mainWindowItems.end(), overworldKeyItems.begin(), overworldKeyItems.end()); } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.SilverRupees"), SECTION_DISPLAY_HIDDEN) == + SECTION_DISPLAY_MAIN_WINDOW) { + while (mainWindowItems.size() % 6) { + mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); + } + for (auto silverRupee : silverRupeeItems) { + uint8_t dungeonId = + OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(static_cast(silverRupee.id)) + .DungeonID(); + RandomizerCheckQuest dungeonQuest = + OTRGlobals::Instance->gRandoContext->GetDungeon(dungeonId)->IsMQ() ? RCQUEST_MQ : RCQUEST_VANILLA; + RandomizerCheckQuest rupeeQuest = + OTRGlobals::Instance->gRandoContext->GetSilverRupeeCounter(static_cast(silverRupee.id)) + .Quest(); + if (dungeonQuest == rupeeQuest) { + mainWindowItems.push_back(silverRupee); + } + } + } + shouldUpdateVectors = false; } @@ -1674,6 +1899,13 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BeanSouls"), SECTION_DISPLAY_HIDDEN) == + SECTION_DISPLAY_SEPARATE) { + BeginFloatingWindows("Bean Soul Tracker"); + DrawItemsInRows(beanSoulItems); + EndFloatingWindows(); + } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Boss Soul Tracker"); @@ -1695,6 +1927,28 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.SilverRupees"), SECTION_DISPLAY_HIDDEN) == + SECTION_DISPLAY_SEPARATE) { + std::vector questMatchingSilverRupeeItems; + for (auto silverRupee : silverRupeeItems) { + uint8_t dungeonId = OTRGlobals::Instance->gRandoContext + ->GetSilverRupeeCounter(static_cast(silverRupee.id)) + .DungeonID(); + RandomizerCheckQuest dungeonQuest = + OTRGlobals::Instance->gRandoContext->GetDungeon(dungeonId)->IsMQ() ? RCQUEST_MQ : RCQUEST_VANILLA; + RandomizerCheckQuest rupeeQuest = + OTRGlobals::Instance->gRandoContext + ->GetSilverRupeeCounter(static_cast(silverRupee.id)) + .Quest(); + if (dungeonQuest == rupeeQuest) { + questMatchingSilverRupeeItems.push_back(silverRupee); + } + } + BeginFloatingWindows("Silver Rupee Tracker"); + DrawItemsInRows(questMatchingSilverRupeeItems); + EndFloatingWindows(); + } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { BeginFloatingWindows("Fishing Pole Tracker"); @@ -1914,10 +2168,12 @@ void ItemTrackerSettingsWindow::DrawElement() { } SohGui::mSohMenu->MenuDrawItem(gregTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(triforcePieceTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(beanSoulsTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(bossSoulsTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(ocarinaButtonTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(overworldKeysTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(fishingPoleTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(silverRupeeTracking, 250, THEME_COLOR); if (CVarCombobox("Total Checks", CVAR_TRACKER_ITEM("TotalChecks.DisplayType"), minimalDisplayTypes, ComboboxOptions() @@ -2028,6 +2284,18 @@ void RegisterItemTrackerWidgets() { ; SohGui::mSohMenu->AddSearchWidget({ gregTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + beanSoulsTracking = { .name = "Bean Souls", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + beanSoulsTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.BeanSouls")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ beanSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + bossSoulsTracking = { .name = "Boss Souls", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; bossSoulsTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.BossSouls")) .Options(ComboboxOptions() @@ -2087,6 +2355,16 @@ void RegisterItemTrackerWidgets() { .ComboMap(extendedDisplayTypes)) .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); ; + silverRupeeTracking = { .name = "Silver Rupees", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + silverRupeeTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.SilverRupees")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + SohGui::mSohMenu->AddSearchWidget( { fishingPoleTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h index 85a2b63a030..b800c8929f0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h @@ -37,6 +37,7 @@ static std::vector itemTrackerWindowIDs = { "Item Tracker", "Boss Soul Tracker", "Ocarina Button Tracker", "Overworld Key Tracker", + "Silver Rupee Tracker", "Fishing Pole Tracker", "Personal Notes", "Total Checks" }; diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index ade5dd1630a..d829e4880b7 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -251,6 +251,33 @@ extern "C" void Randomizer_InitSaveFile() { // Go away Ruto (Water Temple first cutscene). gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10); + if (Randomizer_GetSettingValue(RSK_SKIP_PLANTING_BEANS) && + !(Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_BEANS_ONLY || + Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_ALL)) { + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6); + gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24); + gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3); + gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9); + gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1); + gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18); + gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3); + } + + if (Randomizer_GetSettingValue(RSK_SHUFFLE_BEAN_SOULS) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_DESERT_COLOSSUS_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_GERUDO_VALLEY_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_GRAVEYARD_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_KOKIRI_FOREST_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_LAKE_HYLIA_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_LOST_WOODS_BEAN_SOUL); + Flags_SetRandomizerInf(RAND_INF_ZORAS_RIVER_BEAN_SOUL); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A); Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT); @@ -263,6 +290,10 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OPEN_CHEST) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_WALLET); } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index a7dbb38d6c9..7e00d0ff939 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -214,12 +214,14 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]); OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); + OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF); OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass/Bushes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WidgetType::Combobox, RO_SHUFFLE_GRASS_OFF); OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WidgetType::Combobox, RO_SHUFFLE_CRATES_OFF); OPT_BOOL(RSK_SHUFFLE_TREES, "Shuffle Trees", CVAR_RANDOMIZER_SETTING("ShuffleTrees"), mOptionDescriptions[RSK_SHUFFLE_TREES]); + OPT_BOOL(RSK_SHUFFLE_BUSHES, "Shuffle Bushes", CVAR_RANDOMIZER_SETTING("ShuffleBushes"), mOptionDescriptions[RSK_SHUFFLE_BUSHES]); OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); OPT_U8(RSK_SHUFFLE_MERCHANTS, "Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE); OPT_U8(RSK_MERCHANT_PRICES, "Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE); @@ -236,6 +238,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SHUFFLE_ADULT_TRADE, "Shuffle Adult Trade", CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]); OPT_U8(RSK_SHUFFLE_CHEST_MINIGAME, "Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}); OPT_BOOL(RSK_SHUFFLE_100_GS_REWARD, "Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); + OPT_BOOL(RSK_SHUFFLE_BEAN_SOULS, "Shuffle Bean Souls", CVAR_RANDOMIZER_SETTING("ShuffleBeanSouls"), mOptionDescriptions[RSK_SHUFFLE_BEAN_SOULS], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); OPT_U8(RSK_SHUFFLE_BOSS_SOULS, "Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox); OPT_BOOL(RSK_SHUFFLE_DEKU_STICK_BAG, "Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); OPT_BOOL(RSK_SHUFFLE_DEKU_NUT_BAG, "Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); @@ -269,12 +272,15 @@ void Settings::CreateOptions() { OPT_U8(RSK_KEYRINGS_BOTTOM_OF_THE_WELL, "Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::Combobox, 0); OPT_U8(RSK_KEYRINGS_GTG, "Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::Combobox, 0); OPT_U8(RSK_KEYRINGS_GANONS_CASTLE, "Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::Combobox, 0); + OPT_U8(RSK_SHUFFLE_SILVER_RUPEES, "Shuffle Silver Rupees", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSilverRupees"), mOptionDescriptions[RSK_SHUFFLE_SILVER_RUPEES], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_VANILLA); + OPT_BOOL(RSK_BOTTOMLESS_SILVER_RUPEE_POUCH, "Add Bottomless Silver Rupee Pouch", CVAR_RANDOMIZER_SETTING("BottomlessSilverRupeePouch"), mOptionDescriptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH]); //Dummied out due to redundancy with TimeSavers.SkipChildStealth until such a time that logic needs to consider child stealth e.g. because it's freestanding checks are added to freestanding shuffle. //To undo this dummying, readd this setting to an OptionGroup so it appears in the UI, then edit the timesaver check hooks to look at this, and the timesaver setting to lock itself as needed. OPT_BOOL(RSK_SKIP_CHILD_STEALTH, "Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); + OPT_BOOL(RSK_SKIP_PLANTING_BEANS, "Skip Planting Beans", CVAR_RANDOMIZER_SETTING("SkipPlantingBeans"), mOptionDescriptions[RSK_SKIP_PLANTING_BEANS]); OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 10); OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]); OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE); @@ -1261,6 +1267,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], &mOptions[RSK_SHUFFLE_FISHING_POLE], @@ -1303,6 +1310,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], &mOptions[RSK_SHUFFLE_TREES], + &mOptions[RSK_SHUFFLE_BUSHES], &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_MERCHANT_PRICES], &mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE], @@ -1317,6 +1325,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES], &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_100_GS_REWARD], + &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_SHUFFLE_BOSS_SOULS], &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], &mOptions[RSK_SHUFFLE_STONE_FAIRIES], @@ -1327,31 +1336,31 @@ void Settings::CreateOptions() { WidgetContainerType::COLUMN); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS_IMGUI] = OptionGroup::SubGroup("Shuffle Dungeon Items", - { - &mOptions[RSK_SHUFFLE_DUNGEON_REWARDS], - &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], - &mOptions[RSK_KEYSANITY], - &mOptions[RSK_GERUDO_KEYS], - &mOptions[RSK_BOSS_KEYSANITY], - &mOptions[RSK_GANONS_BOSS_KEY], - &mOptions[RSK_LACS_STONE_COUNT], - &mOptions[RSK_LACS_MEDALLION_COUNT], - &mOptions[RSK_LACS_DUNGEON_COUNT], - &mOptions[RSK_LACS_REWARD_COUNT], - &mOptions[RSK_LACS_TOKEN_COUNT], - &mOptions[RSK_LACS_OPTIONS], - &mOptions[RSK_KEYRINGS], - &mOptions[RSK_KEYRINGS_RANDOM_COUNT], - &mOptions[RSK_KEYRINGS_GERUDO_FORTRESS], - &mOptions[RSK_KEYRINGS_FOREST_TEMPLE], - &mOptions[RSK_KEYRINGS_FIRE_TEMPLE], - &mOptions[RSK_KEYRINGS_WATER_TEMPLE], - &mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE], - &mOptions[RSK_KEYRINGS_SHADOW_TEMPLE], - &mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL], - &mOptions[RSK_KEYRINGS_GTG], - &mOptions[RSK_KEYRINGS_GANONS_CASTLE], - }, + { &mOptions[RSK_SHUFFLE_DUNGEON_REWARDS], + &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], + &mOptions[RSK_KEYSANITY], + &mOptions[RSK_GERUDO_KEYS], + &mOptions[RSK_BOSS_KEYSANITY], + &mOptions[RSK_GANONS_BOSS_KEY], + &mOptions[RSK_LACS_STONE_COUNT], + &mOptions[RSK_LACS_MEDALLION_COUNT], + &mOptions[RSK_LACS_DUNGEON_COUNT], + &mOptions[RSK_LACS_REWARD_COUNT], + &mOptions[RSK_LACS_TOKEN_COUNT], + &mOptions[RSK_LACS_OPTIONS], + &mOptions[RSK_KEYRINGS], + &mOptions[RSK_KEYRINGS_RANDOM_COUNT], + &mOptions[RSK_KEYRINGS_GERUDO_FORTRESS], + &mOptions[RSK_KEYRINGS_FOREST_TEMPLE], + &mOptions[RSK_KEYRINGS_FIRE_TEMPLE], + &mOptions[RSK_KEYRINGS_WATER_TEMPLE], + &mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE], + &mOptions[RSK_KEYRINGS_SHADOW_TEMPLE], + &mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL], + &mOptions[RSK_KEYRINGS_GTG], + &mOptions[RSK_KEYRINGS_GANONS_CASTLE], + &mOptions[RSK_SHUFFLE_SILVER_RUPEES], + &mOptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH] }, WidgetContainerType::COLUMN); mOptionGroups[RSG_ITEMS_IMGUI_TABLE] = OptionGroup::SubGroup("Items", { @@ -1363,7 +1372,7 @@ void Settings::CreateOptions() { mOptionGroups[RSG_TIMESAVERS_IMGUI] = OptionGroup::SubGroup( "Timesavers", { &mOptions[RSK_BIG_POE_COUNT], &mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_EPONA_RACE], - &mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_SKIP_SCARECROWS_SONG] }, + &mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_SKIP_SCARECROWS_SONG], &mOptions[RSK_SKIP_PLANTING_BEANS] }, WidgetContainerType::COLUMN); mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI] = OptionGroup::SubGroup("", { @@ -1560,10 +1569,12 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], &mOptions[RSK_SHUFFLE_TREES], + &mOptions[RSK_SHUFFLE_BUSHES], &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], &mOptions[RSK_SHUFFLE_MERCHANTS], @@ -1581,6 +1592,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_CHEST_MINIGAME], &mOptions[RSK_SHUFFLE_100_GS_REWARD], + &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_SHUFFLE_BOSS_SOULS], &mOptions[RSK_SHUFFLE_DEKU_STICK_BAG], &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], @@ -1591,30 +1603,30 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_SONG_FAIRIES], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = - OptionGroup("Shuffle Dungeon Items", { - &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], - &mOptions[RSK_KEYSANITY], - &mOptions[RSK_GERUDO_KEYS], - &mOptions[RSK_BOSS_KEYSANITY], - &mOptions[RSK_GANONS_BOSS_KEY], - &mOptions[RSK_LACS_STONE_COUNT], - &mOptions[RSK_LACS_MEDALLION_COUNT], - &mOptions[RSK_LACS_DUNGEON_COUNT], - &mOptions[RSK_LACS_REWARD_COUNT], - &mOptions[RSK_LACS_TOKEN_COUNT], - &mOptions[RSK_LACS_OPTIONS], - &mOptions[RSK_KEYRINGS], - &mOptions[RSK_KEYRINGS_RANDOM_COUNT], - &mOptions[RSK_KEYRINGS_GERUDO_FORTRESS], - &mOptions[RSK_KEYRINGS_FOREST_TEMPLE], - &mOptions[RSK_KEYRINGS_FIRE_TEMPLE], - &mOptions[RSK_KEYRINGS_WATER_TEMPLE], - &mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE], - &mOptions[RSK_KEYRINGS_SHADOW_TEMPLE], - &mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL], - &mOptions[RSK_KEYRINGS_GTG], - &mOptions[RSK_KEYRINGS_GANONS_CASTLE], - }); + OptionGroup("Shuffle Dungeon Items", { &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], + &mOptions[RSK_KEYSANITY], + &mOptions[RSK_GERUDO_KEYS], + &mOptions[RSK_BOSS_KEYSANITY], + &mOptions[RSK_GANONS_BOSS_KEY], + &mOptions[RSK_LACS_STONE_COUNT], + &mOptions[RSK_LACS_MEDALLION_COUNT], + &mOptions[RSK_LACS_DUNGEON_COUNT], + &mOptions[RSK_LACS_REWARD_COUNT], + &mOptions[RSK_LACS_TOKEN_COUNT], + &mOptions[RSK_LACS_OPTIONS], + &mOptions[RSK_KEYRINGS], + &mOptions[RSK_KEYRINGS_RANDOM_COUNT], + &mOptions[RSK_KEYRINGS_GERUDO_FORTRESS], + &mOptions[RSK_KEYRINGS_FOREST_TEMPLE], + &mOptions[RSK_KEYRINGS_FIRE_TEMPLE], + &mOptions[RSK_KEYRINGS_WATER_TEMPLE], + &mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE], + &mOptions[RSK_KEYRINGS_SHADOW_TEMPLE], + &mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL], + &mOptions[RSK_KEYRINGS_GTG], + &mOptions[RSK_KEYRINGS_GANONS_CASTLE], + &mOptions[RSK_SHUFFLE_SILVER_RUPEES], + &mOptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH] }); mOptionGroups[RSG_STARTING_ITEMS] = OptionGroup::SubGroup("Items", { &mOptions[RSK_STARTING_OCARINA], &mOptions[RSK_STARTING_KOKIRI_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD] }); @@ -1652,6 +1664,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_EPONA_RACE], &mOptions[RSK_SKIP_SCARECROWS_SONG], + &mOptions[RSK_SKIP_PLANTING_BEANS], &mOptions[RSK_BIG_POE_COUNT], &mOptions[RSK_COMPLETE_MASK_QUEST], }); @@ -1851,6 +1864,15 @@ const OptionGroup& Settings::GetOptionGroup(const RandomizerSettingGroupKey key) } void Settings::UpdateOptionProperties() { + // If statement for No Logic Only options. + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == + RO_LOGIC_NO_LOGIC) { // CUSTOM CODE BY THELYNK FOR BRANCH "V2 : Add All New Option For Randomizer And More" + // RANDOTODO: Remove when logic is implemented for Silver Rupee Shuffle. + mOptions[RSK_SHUFFLE_SILVER_RUPEES].Disable("This setting is only available for No Logic runs."); + } else { + mOptions[RSK_SHUFFLE_SILVER_RUPEES].Enable(); + } + // Default to hiding bridge opts and the extra sliders. mOptions[RSK_RAINBOW_BRIDGE].AddFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_BRIDGE_OPTIONS].Hide(); @@ -2561,10 +2583,23 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_SLINGBOW_BREAK_BEEHIVES].Disable( "This option is disabled because Shuffle Beehives is not enabled."); } + + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleSilverRupees"), RO_DUNGEON_ITEM_LOC_VANILLA) <= + RO_DUNGEON_ITEM_LOC_VANILLA) { + mOptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH].Disable( + "This option is not available unless Silver Rupees are shuffled."); + } else { + mOptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH].Enable(); + } } void Context::FinalizeSettings(const std::set& excludedLocations, const std::set& enabledTricks) { + // If you have settings that will only work for No Logic, put them in this if statement. + if (mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC)) { + // RANDOTODO: Remove when Logic is implemented for Silver Rupees. + mOptions[RSK_SHUFFLE_SILVER_RUPEES].Set(RO_DUNGEON_ITEM_LOC_VANILLA); + } // if we skip child zelda, we start with zelda's letter, and malon starts // at the ranch, so we should *not* shuffle the weird egg if (mOptions[RSK_SKIP_CHILD_ZELDA]) { @@ -2839,6 +2874,9 @@ void Context::FinalizeSettings(const std::set& excludedLocation (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { this->GetDungeon(GANONS_CASTLE)->SetKeyRing(); } + if (mOptions[RSK_SHUFFLE_SILVER_RUPEES].Get() > RO_DUNGEON_ITEM_LOC_VANILLA) { + mOptions[RSK_BOTTOMLESS_SILVER_RUPEE_POUCH].Set(RO_GENERIC_OFF); + } } auto trials = this->GetTrials()->GetTrialList(); diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index cd24667a098..a9cdcac8e39 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -8,6 +8,12 @@ #include "location.h" namespace Rando { + +struct Identifier { + SceneID scene; + RandomizerCheckQuest quest; + int16_t params; +}; /** * @brief Singleton for storing and accessing static Randomizer-related data * @@ -61,6 +67,7 @@ class StaticData { static void RegisterFreestandingLocations(); static void RegisterGrassLocations(); static void RegisterCrateLocations(); + static void RegisterSilverRupeeLocations(); static void RegisterTreeLocations(); static void InitHashMaps(); static std::array, 17> randomizerFishingPondFish; @@ -83,8 +90,23 @@ class StaticData { static std::unordered_map stoneParamsToHint; static std::unordered_map grottoChestParamsToHint; static std::array hintTextTable; + static std::unordered_map silverTrackerMap; StaticData(); ~StaticData(); }; -} // namespace Rando \ No newline at end of file +} // namespace Rando + +namespace std { +template <> struct hash { + inline size_t operator()(const Rando::Identifier& id) const { + return hash{}(id.scene) ^ hash{}(id.quest) ^ hash{}(id.params); + } +}; + +template <> struct equal_to { + inline bool operator()(const Rando::Identifier& a, const Rando::Identifier& b) const { + return a.scene == b.scene && a.params == b.params && a.quest == b.quest; + } +}; +} // namespace std \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index cbcc926d9bd..9b8c40a2662 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2418,6 +2418,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = Randomizer::GetIceTrapMessage(); } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { messageEntry = Randomizer::GetTriforcePieceMessage(); + } else if (player->getItemEntry.getItemId >= RG_SILVER_RUPEE_FIRST && + player->getItemEntry.getItemId <= RG_SILVER_RUPEE_LAST) { + messageEntry = GetSilverRupeeItemMessage(player->getItemEntry.getItemId); } else { messageEntry = Randomizer_GetCustomGetItemMessage(player); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index d15c0108664..48553c49f7b 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -252,6 +252,12 @@ void SaveManager::LoadRandomizer() { SaveManager::Instance->LoadData("", value); randoContext->GetTrickOption(RandomizerTrick(i)).Set(value); }); + + SaveManager::Instance->LoadArray("silverRupees", RG_SILVER_RUPEE_LAST - RG_SILVER_RUPEE_FIRST + 1, [&](size_t i) { + size_t value; + SaveManager::Instance->LoadData("", value); + randoContext->GetSilverRupeeCounter(static_cast(i + RG_SILVER_RUPEE_FIRST)).SetCollected(value); + }); } void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool fullSave) { @@ -400,6 +406,12 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f SaveManager::Instance->SaveArray("trickOptions", RT_MAX, [&](size_t i) { SaveManager::Instance->SaveData("", randoContext->GetTrickOption(RandomizerTrick(i)).Get()); }); + + SaveManager::Instance->SaveArray("silverRupees", RG_SILVER_RUPEE_LAST - RG_SILVER_RUPEE_FIRST + 1, [&](size_t i) { + SaveManager::Instance->SaveData( + "", + randoContext->GetSilverRupeeCounter(static_cast(i + RG_SILVER_RUPEE_FIRST)).GetCollected()); + }); } // Init() here is an extension of InitSram, and thus not truly an initializer for SaveManager itself. don't put any diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp index c80293a53c0..1a940059eb3 100644 --- a/soh/soh/SohGui/ImGuiUtils.cpp +++ b/soh/soh/SohGui/ImGuiUtils.cpp @@ -133,6 +133,10 @@ std::map gregMapping = { { ITEM_RUPEE_GREEN, { ITEM_RUPEE_GREEN, "ITEM_RUPEE_GREEN", "ITEM_RUPEE_GREEN_Faded", gRupeeCounterIconTex } } }; +std::map silverRupeeMapping = { + { ITEM_RUPEE_GREEN, { ITEM_RUPEE_GREEN, "ITEM_RUPEE_SILVER", "ITEM_RUPEE_SILVER_Faded", gRupeeCounterIconTex } } +}; + std::map triforcePieceMapping = { { RG_TRIFORCE_PIECE, { RG_TRIFORCE_PIECE, "RG_TRIFORCE_PIECE", "RG_TRIFORCE_PIECE_Faded", gTriforcePieceTex } } }; @@ -216,6 +220,16 @@ void RegisterImGuiItemIcons() { entry.second.texturePath, gregFadedGreen); } + for (const auto& entry : silverRupeeMapping) { + ImVec4 silver = ImVec4(0.7f, 0.7f, 0.7f, 1.0f); + ImVec4 silverFaded = silver; + silverFaded.w = 0.3f; + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, + silver); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, + entry.second.texturePath, silverFaded); + } + for (const auto& entry : triforcePieceMapping) { Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 844f18687a8..d3cbe056e65 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -293,6 +293,10 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("BetterOwl")) .Options(CheckboxOptions().Tooltip( "The default response to Kaepora Gaebora is always that you understood what he said.")); + AddWidget(path, "Allow Dropping Throw-Only Objects", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("DropThrowOnlyObjects")) + .Options(CheckboxOptions().Tooltip("Allows normally throw-only objects (such as Cuccos, pots, grass, and small " + "rocks) to be dropped by pressing A while standing still.")); AddWidget(path, "Convenience", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Quit Fishing at Door", WIDGET_CVAR_CHECKBOX) @@ -1630,6 +1634,17 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("ExtraTraps.Teleport")) .PreFunc( [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); + AddWidget(path, "Nightmare Traps:", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { + info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; + }); + AddWidget(path, "Pocket Traps", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("ExtraTraps.Pocket")) + .PreFunc( + [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); + AddWidget(path, "Perma Death Traps", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("ExtraTraps.Permadeath")) + .PreFunc( + [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); path.column = SECTION_COLUMN_2; AddWidget(path, "Enemy Randomizer", WIDGET_CVAR_COMBOBOX) @@ -1740,6 +1755,9 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Keese and Guay no longer target you and simply ignore you as if you were wearing the " "Skull Mask.")); + AddWidget(path, "Like Like don't Steal Items", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_CHEAT("NoLikeLikeItemSteal")) + .Options(CheckboxOptions().Tooltip("Prevents Like Likes from being able to steal your equipments.")); AddWidget(path, "Disable Haunted Wasteland Sandstorm", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_CHEAT("DisableSandstorm")) .Options(CheckboxOptions().Tooltip("Disables sandstorm effect in Haunted Wasteland.")); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index b6bf5ecdf90..bf2acdc507d 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1195,6 +1195,7 @@ typedef enum { PARTICLE_PINK, PARTICLE_BRIGHT_RED, PARTICLE_BLUE, + PARTICLE_DARK_PURPLE } Item00ParticleColors; void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry) { @@ -1231,21 +1232,42 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry colorIndex = PARTICLE_BRIGHT_GREEN; break; case RG_BOLERO_OF_FIRE: + case RG_DODONGOS_CAVERN_MQ_SILVER_RUPEE: colorIndex = PARTICLE_RED; break; case RG_SERENADE_OF_WATER: case RG_BOTTLE_WITH_FISH: + case RG_ICE_CAVERN_SLIDING_SILVER_RUPEE: + case RG_ICE_CAVERN_SPINNING_BLADES_SILVER_RUPEE: colorIndex = PARTICLE_CYAN; break; case RG_REQUIEM_OF_SPIRIT: + case RG_SPIRIT_GATE_SILVER_RUPEE: + case RG_SPIRIT_BEAMOS_SILVER_RUPEE: + case RG_SPIRIT_BOULDER_SILVER_RUPEE: + case RG_SPIRIT_MQ_LOBBY_SILVER_RUPEE: colorIndex = PARTICLE_ORANGE; break; case RG_NOCTURNE_OF_SHADOW: case RG_BOTTLE_WITH_POE: + case RG_SHADOW_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE: + case RG_SHADOW_INVISIBLE_SPIKES_SILVER_RUPEE: + case RG_SHADOW_MQ_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_MQ_OUTSIDE_SPIKE_RAIN_SILVER_RUPEE: + case RG_SHADOW_MQ_INVISIBLE_SCYTHE_SILVER_RUPEE: + case RG_SHADOW_MQ_INVISIBLE_SPIKES_SILVER_RUPEE: + case RG_BOTTOM_OF_THE_WELL_SILVER_RUPEE: colorIndex = PARTICLE_VIOLET; break; case RG_PRELUDE_OF_LIGHT: case RG_BOTTLE_WITH_BIG_POE: + case RG_GERUDO_TRAINING_GROUNDS_BOULDER_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_LAVA_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_TOILET_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_BOULDER_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_LAVA_SILVER_RUPEE: + case RG_GERUDO_TRAINING_GROUNDS_MQ_TOILET_SILVER_RUPEE: colorIndex = PARTICLE_YELLOW; break; case RG_DEKU_STICK_BAG: @@ -1272,6 +1294,15 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry case RG_BOTTLE_WITH_BLUE_POTION: colorIndex = PARTICLE_BLUE; break; + case RG_FIRE_TRIAL_SILVER_RUPEE: + case RG_FIRE_TRIAL_MQ_SILVER_RUPEE: + case RG_SPIRIT_TRIAL_SILVER_RUPEE: + case RG_FOREST_TRIAL_SILVER_RUPEE: + case RG_LIGHT_TRIAL_SILVER_RUPEE: + case RG_SHADOW_TRIAL_MQ_SILVER_RUPEE: + case RG_WATER_TRIAL_MQ_SILVER_RUPEE: + colorIndex = PARTICLE_DARK_PURPLE; + break; default: return; } @@ -1281,7 +1312,7 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry } // Color of the circle for the particles - static Color_RGBA8 mainColors[13][3] = { + static Color_RGBA8 mainColors[14][3] = { { 34, 255, 76 }, // Minuet, Bean Pack, Magic Upgrades, Bottle with Green Potion, Bottle with Bugs, and Greg { 177, 35, 35 }, // Bolero { 115, 251, 253 }, // Serenade and Bottle with Fish @@ -1294,11 +1325,12 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry { 19, 120, 182 }, // Progressive Bombchu { 255, 205, 255 }, // Bottle with Fairy { 255, 118, 118 }, // Bottle with Red Potion - { 154, 204, 255 } // Bottle with Blue Fire and Bottle with Blue Potion + { 154, 204, 255 }, // Bottle with Blue Fire and Bottle with Blue Potion + { 118, 10, 143 } // Ganon's Castle Silver Rupees }; // Color of the faded flares stretching off the particles - static Color_RGBA8 flareColors[13][3] = { + static Color_RGBA8 flareColors[14][3] = { { 30, 110, 30 }, // Minuet, Bean Pack, Magic Upgrades, Bottle with Green Potion, Bottle with Bugs, and Greg { 90, 10, 10 }, // Bolero { 35, 35, 177 }, // Serenade and Bottle with Fish @@ -1311,7 +1343,8 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry { 204, 102, 0 }, // Progressive Bombchu { 216, 70, 216 }, // Bottle with Fairy { 90, 10, 10 }, // Bottle with Red Potion - { 35, 35, 177 } // Bottle with Blue Fire + { 35, 35, 177 }, // Bottle with Blue Fire + { 131, 81, 143 } // Ganon's Castle Silver Rupees }; static Vec3f velocity = { 0.0f, 0.0f, 0.0f }; diff --git a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c index 5337a61bc77..1b83f2c65a1 100644 --- a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c +++ b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c @@ -13,6 +13,7 @@ #include "objects/object_tsubo/object_tsubo.h" #include "objects/object_gi_rupy/object_gi_rupy.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED) @@ -117,7 +118,9 @@ void EnGSwitch_Init(Actor* thisx, PlayState* play) { this->numEffects = 20; Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - this->actor.draw = EnGSwitch_DrawRupee; + if (GameInteractor_Should(VB_SILVER_RUPEE_SETUP_DRAW, true, this)) { + this->actor.draw = EnGSwitch_DrawRupee; + } this->actor.shape.yOffset = 700.0f; if (Flags_GetSwitch(play, this->switchFlag)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ You are Shock! ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); @@ -209,30 +212,32 @@ void EnGSwitch_WaitForObject(EnGSwitch* this, PlayState* play) { } void EnGSwitch_SilverRupeeTracker(EnGSwitch* this, PlayState* play) { - static s8 majorScale[] = { 0, 2, 4, 5, 7, 9, 11, 13, 15, 17 }; - - if (this->noteIndex < sCollectedCount) { - if (sCollectedCount < (CVarGetInteger(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 0) ? 10 : 5)) { - // "sound?" - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex); - Audio_PlaySoundTransposed(&gSfxDefaultPos, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]); - this->noteIndex = sCollectedCount; + if (GameInteractor_Should(VB_SILVER_RUPEE_COUNT_CHECK, true, this)) { + static s8 majorScale[] = { 0, 2, 4, 5, 7, 9, 11, 13, 15, 17 }; + + if (this->noteIndex < sCollectedCount) { + if (sCollectedCount < (CVarGetInteger(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 0) ? 10 : 5)) { + // "sound?" + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex); + Audio_PlaySoundTransposed(&gSfxDefaultPos, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]); + this->noteIndex = sCollectedCount; + } } - } - if (sCollectedCount >= this->silverCount) { - // "It is now the end of the century." - // This another reference to Hokuto no Ken. - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 時はまさに世紀末〜 ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); - // "Last!" - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ らすとぉ! ☆☆☆☆☆ \n" VT_RST); - if ((play->sceneNum == SCENE_GERUDO_TRAINING_GROUND) && (this->actor.room == 2)) { - Flags_SetTempClear(play, this->actor.room); - } else { - Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); - Flags_SetSwitch(play, this->switchFlag); + if (sCollectedCount >= this->silverCount) { + // "It is now the end of the century." + // This another reference to Hokuto no Ken. + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 時はまさに世紀末〜 ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); + // "Last!" + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ らすとぉ! ☆☆☆☆☆ \n" VT_RST); + if ((play->sceneNum == SCENE_GERUDO_TRAINING_GROUND) && (this->actor.room == 2)) { + Flags_SetTempClear(play, this->actor.room); + } else { + Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); + Flags_SetSwitch(play, this->switchFlag); + } + Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); + Actor_Kill(&this->actor); } - Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); - Actor_Kill(&this->actor); } } @@ -241,17 +246,19 @@ void EnGSwitch_SilverRupeeIdle(EnGSwitch* this, PlayState* play) { this->actor.shape.rot.y += 0x800; if (this->actor.xyzDistToPlayerSq < 900.0f) { - Rupees_ChangeBy(5); - sCollectedCount++; - Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); - this->actor.world.pos = player->actor.world.pos; - this->actor.world.pos.y += 40.0f; - if (LINK_IS_ADULT) { - this->actor.world.pos.y += 20.0f; + if (GameInteractor_Should(VB_SILVER_RUPEE_COLLECT, true, this)) { + Rupees_ChangeBy(5); + sCollectedCount++; + Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); + this->actor.world.pos = player->actor.world.pos; + this->actor.world.pos.y += 40.0f; + if (LINK_IS_ADULT) { + this->actor.world.pos.y += 20.0f; + } + this->actor.gravity = 0.0f; + this->killTimer = 15; + this->actionFunc = EnGSwitch_SilverRupeeCollected; } - this->actor.gravity = 0.0f; - this->killTimer = 15; - this->actionFunc = EnGSwitch_SilverRupeeCollected; } } diff --git a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c index 831e11b8c38..d94e6dd220b 100644 --- a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c +++ b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c @@ -300,32 +300,35 @@ void EnRr_SetupReleasePlayer(EnRr* this, PlayState* play) { this->wobbleSizeTarget = 2048.0f; tunic = 0; shield = 0; - if (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) != EQUIP_VALUE_SHIELD_MIRROR) { - shield = Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); - if (shield != 0) { - this->eatenShield = shield; - this->retreat = true; + if (GameInteractor_Should(VB_LIKE_LIKE_STEAL_EQUIPMENT, true, this)) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) != EQUIP_VALUE_SHIELD_MIRROR) { + shield = Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); + if (shield != 0) { + this->eatenShield = shield; + this->retreat = true; + } } - } - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) != EQUIP_VALUE_TUNIC_KOKIRI && !IS_RANDO /* Randomizer Save File */) { - tunic = Inventory_DeleteEquipment(play, EQUIP_TYPE_TUNIC); - if (tunic != 0) { - this->eatenTunic = tunic; - this->retreat = true; + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) != EQUIP_VALUE_TUNIC_KOKIRI && !IS_RANDO /* Randomizer Save File */) { + tunic = Inventory_DeleteEquipment(play, EQUIP_TYPE_TUNIC); + if (tunic != 0) { + this->eatenTunic = tunic; + this->retreat = true; + } + } + + switch (EnRr_GetMessage(shield, tunic)) { + case RR_MESSAGE_SHIELD: + Message_StartTextbox(play, 0x305F, NULL); + break; + case RR_MESSAGE_TUNIC: + Message_StartTextbox(play, 0x3060, NULL); + break; + case RR_MESSAGE_TUNIC | RR_MESSAGE_SHIELD: + Message_StartTextbox(play, 0x3061, NULL); + break; } } player->actor.parent = NULL; - switch (EnRr_GetMessage(shield, tunic)) { - case RR_MESSAGE_SHIELD: - Message_StartTextbox(play, 0x305F, NULL); - break; - case RR_MESSAGE_TUNIC: - Message_StartTextbox(play, 0x3060, NULL); - break; - case RR_MESSAGE_TUNIC | RR_MESSAGE_SHIELD: - Message_StartTextbox(play, 0x3061, NULL); - break; - } osSyncPrintf(VT_FGCOL(YELLOW) "%s[%d] : Rr_Catch_Cancel" VT_RST "\n", __FILE__, __LINE__); func_8002F6D4(play, &this->actor, 4.0f, this->actor.shape.rot.y, 12.0f, 8); if (this->actor.colorFilterTimer == 0) { @@ -666,50 +669,53 @@ void EnRr_Death(EnRr* this, PlayState* play) { (SQ(4 - i) * (f32)this->frameCount * 0.003f) + 1.0f; } } else if (this->frameCount >= 95) { - Vec3f dropPos; - - dropPos.x = this->actor.world.pos.x; - dropPos.y = this->actor.world.pos.y; - dropPos.z = this->actor.world.pos.z; - switch (this->eatenShield) { - case 1: - Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_DEKU); - break; - case 2: - Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_HYLIAN); - break; - } - switch (this->eatenTunic) { - case 2: - Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_GORON); - break; - case 3: - Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_ZORA); - break; - } - // "dropped" - osSyncPrintf(VT_FGCOL(GREEN) "「%s」が出た!!" VT_RST "\n", sDropNames[this->dropType]); - switch (this->dropType) { - case RR_DROP_MAGIC: - Item_DropCollectible(play, &dropPos, ITEM00_MAGIC_SMALL); - break; - case RR_DROP_ARROW: - Item_DropCollectible(play, &dropPos, ITEM00_ARROWS_SINGLE); - break; - case RR_DROP_FLEXIBLE: - Item_DropCollectible(play, &dropPos, ITEM00_FLEXIBLE); - break; - case RR_DROP_RUPEE_PURPLE: - Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_PURPLE); - break; - case RR_DROP_RUPEE_RED: - Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_RED); - break; - case RR_DROP_RANDOM_RUPEE: - default: - Item_DropCollectibleRandom(play, &this->actor, &dropPos, 12 << 4); - break; + if (GameInteractor_Should(VB_LIKE_LIKE_DROP_COLLECTIBLE, true, this)) { + Vec3f dropPos; + + dropPos.x = this->actor.world.pos.x; + dropPos.y = this->actor.world.pos.y; + dropPos.z = this->actor.world.pos.z; + switch (this->eatenShield) { + case 1: + Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_DEKU); + break; + case 2: + Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_HYLIAN); + break; + } + switch (this->eatenTunic) { + case 2: + Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_GORON); + break; + case 3: + Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_ZORA); + break; + } + // "dropped" + osSyncPrintf(VT_FGCOL(GREEN) "「%s」が出た!!" VT_RST "\n", sDropNames[this->dropType]); + switch (this->dropType) { + case RR_DROP_MAGIC: + Item_DropCollectible(play, &dropPos, ITEM00_MAGIC_SMALL); + break; + case RR_DROP_ARROW: + Item_DropCollectible(play, &dropPos, ITEM00_ARROWS_SINGLE); + break; + case RR_DROP_FLEXIBLE: + Item_DropCollectible(play, &dropPos, ITEM00_FLEXIBLE); + break; + case RR_DROP_RUPEE_PURPLE: + Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_PURPLE); + break; + case RR_DROP_RUPEE_RED: + Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_RED); + break; + case RR_DROP_RANDOM_RUPEE: + default: + Item_DropCollectibleRandom(play, &this->actor, &dropPos, 12 << 4); + break; + } } + Actor_Kill(&this->actor); } else if (this->frameCount == 88) { Vec3f pos; diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 1fe96d38c67..b83bd3ddd04 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -403,12 +403,14 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { (player->linearVelocity != 0.0f)) || ((player->rideActor != NULL) && (sqrt(this->actor.xyzDistToPlayerSq) < 60.0) && (player->rideActor->speedXZ != 0.0f))) { - if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { - Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, - ((this->unk_14C << 4) | 0x8000)); + if (GameInteractor_Should(VB_BUSH_DROP_ITEM, true, this)) { + if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { + Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, + ((this->unk_14C << 4) | 0x8000)); + } + this->unk_14C = -0x15; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_TREE_SWING); } - this->unk_14C = -0x15; - Audio_PlayActorSound2(&this->actor, NA_SE_EV_TREE_SWING); } } } else { // Leaves diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 7da8447c03a..320be5f2a59 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7382,7 +7382,7 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) { } else if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && !(this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) { - if (this->getItemId != GI_NONE) { + if (GameInteractor_Should(VB_OPEN_CHEST, this->getItemId != GI_NONE)) { GetItemEntry giEntry; if (this->getItemEntry.objectId == OBJECT_INVALID) { giEntry = ItemTable_Retrieve(-this->getItemId);